From b4090ead4d4334e08725323ff72fd355c93b63d5 Mon Sep 17 00:00:00 2001 From: Willem Jan Palenstijn Date: Tue, 4 Sep 2012 22:17:23 +0200 Subject: WINTERMUTE: Convert CRLF to LF --- engines/wintermute/base/gfx/base_image.cpp | 462 ++++---- engines/wintermute/base/gfx/base_image.h | 144 +-- engines/wintermute/base/gfx/base_renderer.cpp | 762 ++++++------ engines/wintermute/base/gfx/base_renderer.h | 442 +++---- engines/wintermute/base/gfx/base_surface.cpp | 298 ++--- engines/wintermute/base/gfx/base_surface.h | 198 ++-- .../base/gfx/osystem/base_render_osystem.cpp | 1208 ++++++++++---------- .../base/gfx/osystem/base_render_osystem.h | 262 ++--- .../base/gfx/osystem/base_surface_osystem.cpp | 858 +++++++------- .../base/gfx/osystem/base_surface_osystem.h | 198 ++-- 10 files changed, 2416 insertions(+), 2416 deletions(-) (limited to 'engines/wintermute/base/gfx') diff --git a/engines/wintermute/base/gfx/base_image.cpp b/engines/wintermute/base/gfx/base_image.cpp index bf11e15307..4b15d563ed 100644 --- a/engines/wintermute/base/gfx/base_image.cpp +++ b/engines/wintermute/base/gfx/base_image.cpp @@ -1,231 +1,231 @@ -/* 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. - * - */ - -/* - * This file is based on WME Lite. - * http://dead-code.org/redir.php?target=wmelite - * Copyright (c) 2011 Jan Nedoma - */ - -#include "engines/wintermute/base/gfx/base_image.h" -#include "engines/wintermute/base/base_file_manager.h" -#include "engines/wintermute/graphics/transparent_surface.h" -#include "graphics/decoders/png.h" -#include "graphics/decoders/jpeg.h" -#include "graphics/decoders/bmp.h" -#include "graphics/decoders/tga.h" -#include "graphics/surface.h" -#include "common/textconsole.h" -#include "common/stream.h" -#include "common/system.h" - -namespace Wintermute { - -////////////////////////////////////////////////////////////////////// -BaseImage::BaseImage() { - _fileManager = BaseFileManager::getEngineInstance(); - _palette = NULL; - _surface = NULL; - _decoder = NULL; - _deletableSurface = NULL; -} - - -////////////////////////////////////////////////////////////////////// -BaseImage::~BaseImage() { - delete _decoder; - if (_deletableSurface) { - _deletableSurface->free(); - } - delete _deletableSurface; -} - -bool BaseImage::loadFile(const Common::String &filename) { - _filename = filename; - _filename.toLowercase(); - if (filename.hasPrefix("savegame:")) { - _decoder = new Graphics::BitmapDecoder(); - } else if (_filename.hasSuffix(".png")) { - _decoder = new Graphics::PNGDecoder(); - } else if (_filename.hasSuffix(".bmp")) { - _decoder = new Graphics::BitmapDecoder(); - } else if (_filename.hasSuffix(".tga")) { - _decoder = new Graphics::TGADecoder(); - } else if (_filename.hasSuffix(".jpg")) { - _decoder = new Graphics::JPEGDecoder(); - } else { - error("BaseImage::loadFile : Unsupported fileformat %s", filename.c_str()); - } - _filename = filename; - Common::SeekableReadStream *file = _fileManager->openFile(filename.c_str()); - if (!file) { - return false; - } - - _decoder->loadStream(*file); - _surface = _decoder->getSurface(); - _palette = _decoder->getPalette(); - _fileManager->closeFile(file); - - return true; -} - -byte BaseImage::getAlphaAt(int x, int y) const { - if (!_surface) { - return 0xFF; - } - uint32 color = *(const uint32 *)_surface->getBasePtr(x, y); - byte r, g, b, a; - _surface->format.colorToARGB(color, a, r, g, b); - return a; -} - -void BaseImage::copyFrom(const Graphics::Surface *surface) { - _surface = _deletableSurface = new Graphics::Surface(); - _deletableSurface->copyFrom(*surface); -} - -////////////////////////////////////////////////////////////////////////// -bool BaseImage::saveBMPFile(const char *filename) const { - warning("BaseImage::saveBMPFile - stubbed"); // TODO - return false; -} - - -////////////////////////////////////////////////////////////////////////// -bool BaseImage::resize(int newWidth, int newHeight) { - // WME Lite used FILTER_BILINEAR with FreeImage_Rescale here. - TransparentSurface temp(*_surface, true); - if (_deletableSurface) { - _deletableSurface->free(); - delete _deletableSurface; - _deletableSurface = NULL; - } - _surface = _deletableSurface = temp.scale((uint16)newWidth, (uint16)newHeight); - temp.free(); - return true; -} - - -////////////////////////////////////////////////////////////////////////// -bool BaseImage::writeBMPToStream(Common::WriteStream *stream) const { - if (!_surface) { - return false; - } - - /* The following is just copied over and inverted to write-ops from the BMP-decoder */ - stream->writeByte('B'); - stream->writeByte('M'); - - /* Since we don't care during reads, we don't care during writes: */ - /* uint32 fileSize = */ - stream->writeUint32LE(54 + _surface->h * _surface->pitch); - /* uint16 res1 = */ - stream->writeUint16LE(0); - /* uint16 res2 = */ - stream->writeUint16LE(0); - const uint32 imageOffset = 54; - stream->writeUint32LE(imageOffset); - - const uint32 infoSize = 40; /* Windows v3 BMP */ - stream->writeUint32LE(infoSize); - - uint32 width = _surface->w; - int32 height = _surface->h; - stream->writeUint32LE(width); - stream->writeUint32LE((uint32)height); - - if (width == 0 || height == 0) { - return false; - } - - if (height < 0) { - warning("Right-side up bitmaps not supported"); - return false; - } - - /* uint16 planes = */ stream->writeUint16LE(1); - const uint16 bitsPerPixel = 24; - stream->writeUint16LE(bitsPerPixel); - - const uint32 compression = 0; - stream->writeUint32LE(compression); - - /* uint32 imageSize = */ - stream->writeUint32LE(_surface->h * _surface->pitch); - /* uint32 pixelsPerMeterX = */ - stream->writeUint32LE(0); - /* uint32 pixelsPerMeterY = */ - stream->writeUint32LE(0); - const uint32 paletteColorCount = 0; - stream->writeUint32LE(paletteColorCount); - /* uint32 colorsImportant = */ - stream->writeUint32LE(0); - - // Start us at the beginning of the image (54 bytes in) - Graphics::PixelFormat format = Graphics::PixelFormat::createFormatCLUT8(); - - // BGRA for 24bpp - if (bitsPerPixel == 24) { - format = Graphics::PixelFormat(4, 8, 8, 8, 8, 8, 16, 24, 0); - } - - Graphics::Surface *surface = _surface->convertTo(format); - - int srcPitch = width * (bitsPerPixel >> 3); - const int extraDataLength = (srcPitch % 4) ? 4 - (srcPitch % 4) : 0; - - for (int32 i = height - 1; i >= 0; i--) { - for (uint32 j = 0; j < width; j++) { - byte b, g, r; - uint32 color = *(uint32 *)surface->getBasePtr(j, i); - surface->format.colorToRGB(color, r, g, b); - stream->writeByte(b); - stream->writeByte(g); - stream->writeByte(r); - } - - for (int k = 0; k < extraDataLength; k++) { - stream->writeByte(0); - } - } - surface->free(); - delete surface; - return true; -} - - -////////////////////////////////////////////////////////////////////////// -bool BaseImage::copyFrom(BaseImage *origImage, int newWidth, int newHeight) { - // WME Lite used FILTER_BILINEAR with FreeImage_Rescale here. - - TransparentSurface temp(*origImage->_surface, false); - if (_deletableSurface) { - _deletableSurface->free(); - delete _deletableSurface; - _deletableSurface = NULL; - } - _surface = _deletableSurface = temp.scale((uint16)newWidth, (uint16)newHeight); - return true; -} - -} // end of namespace Wintermute +/* 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. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#include "engines/wintermute/base/gfx/base_image.h" +#include "engines/wintermute/base/base_file_manager.h" +#include "engines/wintermute/graphics/transparent_surface.h" +#include "graphics/decoders/png.h" +#include "graphics/decoders/jpeg.h" +#include "graphics/decoders/bmp.h" +#include "graphics/decoders/tga.h" +#include "graphics/surface.h" +#include "common/textconsole.h" +#include "common/stream.h" +#include "common/system.h" + +namespace Wintermute { + +////////////////////////////////////////////////////////////////////// +BaseImage::BaseImage() { + _fileManager = BaseFileManager::getEngineInstance(); + _palette = NULL; + _surface = NULL; + _decoder = NULL; + _deletableSurface = NULL; +} + + +////////////////////////////////////////////////////////////////////// +BaseImage::~BaseImage() { + delete _decoder; + if (_deletableSurface) { + _deletableSurface->free(); + } + delete _deletableSurface; +} + +bool BaseImage::loadFile(const Common::String &filename) { + _filename = filename; + _filename.toLowercase(); + if (filename.hasPrefix("savegame:")) { + _decoder = new Graphics::BitmapDecoder(); + } else if (_filename.hasSuffix(".png")) { + _decoder = new Graphics::PNGDecoder(); + } else if (_filename.hasSuffix(".bmp")) { + _decoder = new Graphics::BitmapDecoder(); + } else if (_filename.hasSuffix(".tga")) { + _decoder = new Graphics::TGADecoder(); + } else if (_filename.hasSuffix(".jpg")) { + _decoder = new Graphics::JPEGDecoder(); + } else { + error("BaseImage::loadFile : Unsupported fileformat %s", filename.c_str()); + } + _filename = filename; + Common::SeekableReadStream *file = _fileManager->openFile(filename.c_str()); + if (!file) { + return false; + } + + _decoder->loadStream(*file); + _surface = _decoder->getSurface(); + _palette = _decoder->getPalette(); + _fileManager->closeFile(file); + + return true; +} + +byte BaseImage::getAlphaAt(int x, int y) const { + if (!_surface) { + return 0xFF; + } + uint32 color = *(const uint32 *)_surface->getBasePtr(x, y); + byte r, g, b, a; + _surface->format.colorToARGB(color, a, r, g, b); + return a; +} + +void BaseImage::copyFrom(const Graphics::Surface *surface) { + _surface = _deletableSurface = new Graphics::Surface(); + _deletableSurface->copyFrom(*surface); +} + +////////////////////////////////////////////////////////////////////////// +bool BaseImage::saveBMPFile(const char *filename) const { + warning("BaseImage::saveBMPFile - stubbed"); // TODO + return false; +} + + +////////////////////////////////////////////////////////////////////////// +bool BaseImage::resize(int newWidth, int newHeight) { + // WME Lite used FILTER_BILINEAR with FreeImage_Rescale here. + TransparentSurface temp(*_surface, true); + if (_deletableSurface) { + _deletableSurface->free(); + delete _deletableSurface; + _deletableSurface = NULL; + } + _surface = _deletableSurface = temp.scale((uint16)newWidth, (uint16)newHeight); + temp.free(); + return true; +} + + +////////////////////////////////////////////////////////////////////////// +bool BaseImage::writeBMPToStream(Common::WriteStream *stream) const { + if (!_surface) { + return false; + } + + /* The following is just copied over and inverted to write-ops from the BMP-decoder */ + stream->writeByte('B'); + stream->writeByte('M'); + + /* Since we don't care during reads, we don't care during writes: */ + /* uint32 fileSize = */ + stream->writeUint32LE(54 + _surface->h * _surface->pitch); + /* uint16 res1 = */ + stream->writeUint16LE(0); + /* uint16 res2 = */ + stream->writeUint16LE(0); + const uint32 imageOffset = 54; + stream->writeUint32LE(imageOffset); + + const uint32 infoSize = 40; /* Windows v3 BMP */ + stream->writeUint32LE(infoSize); + + uint32 width = _surface->w; + int32 height = _surface->h; + stream->writeUint32LE(width); + stream->writeUint32LE((uint32)height); + + if (width == 0 || height == 0) { + return false; + } + + if (height < 0) { + warning("Right-side up bitmaps not supported"); + return false; + } + + /* uint16 planes = */ stream->writeUint16LE(1); + const uint16 bitsPerPixel = 24; + stream->writeUint16LE(bitsPerPixel); + + const uint32 compression = 0; + stream->writeUint32LE(compression); + + /* uint32 imageSize = */ + stream->writeUint32LE(_surface->h * _surface->pitch); + /* uint32 pixelsPerMeterX = */ + stream->writeUint32LE(0); + /* uint32 pixelsPerMeterY = */ + stream->writeUint32LE(0); + const uint32 paletteColorCount = 0; + stream->writeUint32LE(paletteColorCount); + /* uint32 colorsImportant = */ + stream->writeUint32LE(0); + + // Start us at the beginning of the image (54 bytes in) + Graphics::PixelFormat format = Graphics::PixelFormat::createFormatCLUT8(); + + // BGRA for 24bpp + if (bitsPerPixel == 24) { + format = Graphics::PixelFormat(4, 8, 8, 8, 8, 8, 16, 24, 0); + } + + Graphics::Surface *surface = _surface->convertTo(format); + + int srcPitch = width * (bitsPerPixel >> 3); + const int extraDataLength = (srcPitch % 4) ? 4 - (srcPitch % 4) : 0; + + for (int32 i = height - 1; i >= 0; i--) { + for (uint32 j = 0; j < width; j++) { + byte b, g, r; + uint32 color = *(uint32 *)surface->getBasePtr(j, i); + surface->format.colorToRGB(color, r, g, b); + stream->writeByte(b); + stream->writeByte(g); + stream->writeByte(r); + } + + for (int k = 0; k < extraDataLength; k++) { + stream->writeByte(0); + } + } + surface->free(); + delete surface; + return true; +} + + +////////////////////////////////////////////////////////////////////////// +bool BaseImage::copyFrom(BaseImage *origImage, int newWidth, int newHeight) { + // WME Lite used FILTER_BILINEAR with FreeImage_Rescale here. + + TransparentSurface temp(*origImage->_surface, false); + if (_deletableSurface) { + _deletableSurface->free(); + delete _deletableSurface; + _deletableSurface = NULL; + } + _surface = _deletableSurface = temp.scale((uint16)newWidth, (uint16)newHeight); + return true; +} + +} // end of namespace Wintermute diff --git a/engines/wintermute/base/gfx/base_image.h b/engines/wintermute/base/gfx/base_image.h index 560a5f0d74..6d01b84184 100644 --- a/engines/wintermute/base/gfx/base_image.h +++ b/engines/wintermute/base/gfx/base_image.h @@ -1,72 +1,72 @@ -/* 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. - * - */ - -/* - * This file is based on WME Lite. - * http://dead-code.org/redir.php?target=wmelite - * Copyright (c) 2011 Jan Nedoma - */ - -#ifndef WINTERMUTE_BASE_IMAGE_H -#define WINTERMUTE_BASE_IMAGE_H - -#include "graphics/surface.h" -#include "graphics/pixelformat.h" -#include "graphics/decoders/image_decoder.h" -#include "common/endian.h" -#include "common/str.h" -#include "common/stream.h" - -namespace Wintermute { -class BaseSurface; -class BaseFileManager; -class BaseImage { - -public: - BaseImage(); - ~BaseImage(); - - bool loadFile(const Common::String &filename); - const Graphics::Surface *getSurface() const { - return _surface; - }; - const byte *getPalette() const { - return _palette; - } - byte getAlphaAt(int x, int y) const; - bool writeBMPToStream(Common::WriteStream *stream) const; - bool resize(int newWidth, int newHeight); - bool saveBMPFile(const char *filename) const; - bool copyFrom(BaseImage *origImage, int newWidth = 0, int newHeight = 0); - void copyFrom(const Graphics::Surface *surface); -private: - Common::String _filename; - Graphics::ImageDecoder *_decoder; - const Graphics::Surface *_surface; - Graphics::Surface *_deletableSurface; - const byte *_palette; - BaseFileManager *_fileManager; -}; - -} // end of namespace Wintermute - -#endif +/* 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. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_BASE_IMAGE_H +#define WINTERMUTE_BASE_IMAGE_H + +#include "graphics/surface.h" +#include "graphics/pixelformat.h" +#include "graphics/decoders/image_decoder.h" +#include "common/endian.h" +#include "common/str.h" +#include "common/stream.h" + +namespace Wintermute { +class BaseSurface; +class BaseFileManager; +class BaseImage { + +public: + BaseImage(); + ~BaseImage(); + + bool loadFile(const Common::String &filename); + const Graphics::Surface *getSurface() const { + return _surface; + }; + const byte *getPalette() const { + return _palette; + } + byte getAlphaAt(int x, int y) const; + bool writeBMPToStream(Common::WriteStream *stream) const; + bool resize(int newWidth, int newHeight); + bool saveBMPFile(const char *filename) const; + bool copyFrom(BaseImage *origImage, int newWidth = 0, int newHeight = 0); + void copyFrom(const Graphics::Surface *surface); +private: + Common::String _filename; + Graphics::ImageDecoder *_decoder; + const Graphics::Surface *_surface; + Graphics::Surface *_deletableSurface; + const byte *_palette; + BaseFileManager *_fileManager; +}; + +} // end of namespace Wintermute + +#endif diff --git a/engines/wintermute/base/gfx/base_renderer.cpp b/engines/wintermute/base/gfx/base_renderer.cpp index 202c864683..9205438a5b 100644 --- a/engines/wintermute/base/gfx/base_renderer.cpp +++ b/engines/wintermute/base/gfx/base_renderer.cpp @@ -1,381 +1,381 @@ -/* 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. - * - */ - -/* - * This file is based on WME Lite. - * http://dead-code.org/redir.php?target=wmelite - * Copyright (c) 2011 Jan Nedoma - */ - -#include "engines/wintermute/base/base_active_rect.h" -#include "engines/wintermute/base/gfx/base_renderer.h" -#include "engines/wintermute/base/gfx/base_surface.h" -#include "engines/wintermute/base/base_sub_frame.h" -#include "engines/wintermute/base/base_region.h" -#include "engines/wintermute/platform_osystem.h" -#include "engines/wintermute/base/base_persistence_manager.h" - -namespace Wintermute { - -////////////////////////////////////////////////////////////////////// -BaseRenderer::BaseRenderer(BaseGame *inGame) : BaseClass(inGame) { - _window = 0; - _clipperWindow = 0; - _active = false; - _ready = false; - _windowed = true; - _forceAlphaColor = 0x00; - - _indicatorDisplay = false; - _indicatorColor = BYTETORGBA(255, 0, 0, 128); - _indicatorProgress = 0; - _indicatorX = -1; - _indicatorY = -1; - _indicatorWidth = -1; - _indicatorHeight = 8; - _indicatorWidthDrawn = 0; - - _loadImageName = ""; - _saveImageName = ""; - _saveLoadImage = NULL; - _loadInProgress = false; - _hasDrawnSaveLoadImage = false; - - _saveImageX = _saveImageY = 0; - _loadImageX = _loadImageY = 0; - - _width = _height = _bPP = 0; - BasePlatform::setRectEmpty(&_monitorRect); - - _realWidth = _realHeight = 0; - _drawOffsetX = _drawOffsetY = 0; -} - - -////////////////////////////////////////////////////////////////////// -BaseRenderer::~BaseRenderer() { - deleteRectList(); - unclipCursor(); - delete _saveLoadImage; -} - - -////////////////////////////////////////////////////////////////////// -void BaseRenderer::initLoop() { - deleteRectList(); -} - -void BaseRenderer::initIndicator() { - if (_indicatorY == -1) { - _indicatorY = _height - _indicatorHeight; - } - if (_indicatorX == -1) { - _indicatorX = 0; - } - if (_indicatorWidth == -1) { - _indicatorWidth = _width; - } -} - -void BaseRenderer::setIndicator(int width, int height, int x, int y, uint32 color) { - _indicatorWidth = width; - _indicatorHeight = height; - _indicatorX = x; - _indicatorY = y; - _indicatorColor = color; -} - -void BaseRenderer::setIndicatorVal(int value) { - bool redisplay = (_indicatorProgress != value); - _indicatorProgress = value; - if (redisplay) - displayIndicator(); -} - -void BaseRenderer::setLoadingScreen(const char *filename, int x, int y) { - // TODO: Handle NULL - _loadImageName = filename; - _loadImageX = x; - _loadImageY = y; -} - -void BaseRenderer::setSaveImage(const char *filename, int x, int y) { - // TODO: Handle NULL - _saveImageName = filename; - _saveImageX = x; - _saveImageY = y; -} - -void BaseRenderer::initSaveLoad(bool isSaving, bool quickSave) { - _indicatorDisplay = true; - _indicatorProgress = 0; - _hasDrawnSaveLoadImage = false; - - if (isSaving && !quickSave) { - delete _saveLoadImage; - _saveLoadImage = NULL; - if (_saveImageName.size()) { - _saveLoadImage = createSurface(); - - if (!_saveLoadImage || DID_FAIL(_saveLoadImage->create(_saveImageName, true, 0, 0, 0))) { - delete _saveLoadImage; - _saveLoadImage = NULL; - } - } - } else { - delete _saveLoadImage; - _saveLoadImage = NULL; - if (_loadImageName.size()) { - _saveLoadImage = createSurface(); - - if (!_saveLoadImage || DID_FAIL(_saveLoadImage->create(_loadImageName, true, 0, 0, 0))) { - delete _saveLoadImage; - _saveLoadImage = NULL; - } - } - _loadInProgress = true; - } -} - -void BaseRenderer::endSaveLoad() { - _loadInProgress = false; - _indicatorDisplay = false; - _indicatorWidthDrawn = 0; - - delete _saveLoadImage; - _saveLoadImage = NULL; -} - -void BaseRenderer::persistSaveLoadImages(BasePersistenceManager *persistMgr) { - persistMgr->transfer(TMEMBER(_loadImageName)); - persistMgr->transfer(TMEMBER(_saveImageName)); - persistMgr->transfer(TMEMBER(_saveImageX)); - persistMgr->transfer(TMEMBER(_saveImageY)); - persistMgr->transfer(TMEMBER(_loadImageX)); - persistMgr->transfer(TMEMBER(_loadImageY)); -} - -////////////////////////////////////////////////////////////////////// -BaseObject *BaseRenderer::getObjectAt(int x, int y) { - Point32 point; - point.x = x; - point.y = y; - - for (int i = _rectList.size() - 1; i >= 0; i--) { - if (BasePlatform::ptInRect(&_rectList[i]->_rect, point)) { - if (_rectList[i]->_precise) { - // frame - if (_rectList[i]->_frame) { - int xx = (int)((_rectList[i]->_frame->getRect().left + x - _rectList[i]->_rect.left + _rectList[i]->_offsetX) / (float)((float)_rectList[i]->_zoomX / (float)100)); - int yy = (int)((_rectList[i]->_frame->getRect().top + y - _rectList[i]->_rect.top + _rectList[i]->_offsetY) / (float)((float)_rectList[i]->_zoomY / (float)100)); - - if (_rectList[i]->_frame->_mirrorX) { - int width = _rectList[i]->_frame->getRect().right - _rectList[i]->_frame->getRect().left; - xx = width - xx; - } - - if (_rectList[i]->_frame->_mirrorY) { - int height = _rectList[i]->_frame->getRect().bottom - _rectList[i]->_frame->getRect().top; - yy = height - yy; - } - - if (!_rectList[i]->_frame->_surface->isTransparentAt(xx, yy)) { - return _rectList[i]->_owner; - } - } - // region - else if (_rectList[i]->_region) { - if (_rectList[i]->_region->pointInRegion(x + _rectList[i]->_offsetX, y + _rectList[i]->_offsetY)) { - return _rectList[i]->_owner; - } - } - } else { - return _rectList[i]->_owner; - } - } - } - - return (BaseObject *)NULL; -} - - -////////////////////////////////////////////////////////////////////////// -void BaseRenderer::deleteRectList() { - for (uint32 i = 0; i < _rectList.size(); i++) { - delete _rectList[i]; - } - _rectList.clear(); -} - -////////////////////////////////////////////////////////////////////// -bool BaseRenderer::initRenderer(int width, int height, bool windowed) { - return STATUS_FAILED; -} - - -////////////////////////////////////////////////////////////////////// -void BaseRenderer::onWindowChange() { -} - - -////////////////////////////////////////////////////////////////////////// -bool BaseRenderer::windowedBlt() { - return STATUS_FAILED; -} - - -////////////////////////////////////////////////////////////////////////// -bool BaseRenderer::setup2D(bool Force) { - return STATUS_FAILED; -} - - -////////////////////////////////////////////////////////////////////////// -bool BaseRenderer::setupLines() { - return STATUS_FAILED; -} - -////////////////////////////////////////////////////////////////////////// -bool BaseRenderer::drawLine(int x1, int y1, int x2, int y2, uint32 color) { - return STATUS_FAILED; -} - - -////////////////////////////////////////////////////////////////////////// -bool BaseRenderer::drawRect(int x1, int y1, int x2, int y2, uint32 color, int width) { - for (int i = 0; i < width; i++) { - drawLine(x1 + i, y1 + i, x2 - i, y1 + i, color); // up - drawLine(x1 + i, y2 - i, x2 - i + 1, y2 - i, color); // down - - drawLine(x1 + i, y1 + i, x1 + i, y2 - i, color); // left - drawLine(x2 - i, y1 + i, x2 - i, y2 - i + 1, color); // right - } - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool BaseRenderer::setViewport(int left, int top, int right, int bottom) { - return STATUS_FAILED; -} - - -////////////////////////////////////////////////////////////////////////// -bool BaseRenderer::setScreenViewport() { - return setViewport(_drawOffsetX, _drawOffsetY, _width + _drawOffsetX, _height + _drawOffsetY); -} - - -////////////////////////////////////////////////////////////////////////// -bool BaseRenderer::setViewport(Rect32 *rect) { - return setViewport(rect->left + _drawOffsetX, - rect->top + _drawOffsetY, - rect->right + _drawOffsetX, - rect->bottom + _drawOffsetY); -} - - -////////////////////////////////////////////////////////////////////////// -bool BaseRenderer::clipCursor() { - // TODO: Reimplement this. (Currently aspect-indpendence isn't quite finished) - /* - if (!_windowed) { - Rect32 rc; - GetWindowRect(_window, &rc); - - // if "maintain aspect ratio" is in effect, lock mouse to visible area - rc.left = _drawOffsetX; - rc.top = _drawOffsetY; - rc.right = rc.left + _width; - rc.bottom = rc.top + _height; - - ::ClipCursor(&rc); - } - */ - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -bool BaseRenderer::unclipCursor() { - /* - if (!_windowed) ::ClipCursor(NULL); - */ - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -bool BaseRenderer::pointInViewport(Point32 *p) { - if (p->x < _drawOffsetX) { - return false; - } - if (p->y < _drawOffsetY) { - return false; - } - if (p->x > _drawOffsetX + _width) { - return false; - } - if (p->y > _drawOffsetY + _height) { - return false; - } - - return true; -} - -void BaseRenderer::addRectToList(BaseActiveRect *rect) { - _rectList.push_back(rect); -} - -////////////////////////////////////////////////////////////////////////// -bool BaseRenderer::displayIndicator() { - if (!_indicatorDisplay || !_indicatorProgress) { - return STATUS_OK; - } - if (_saveLoadImage && !_hasDrawnSaveLoadImage) { - Rect32 rc; - BasePlatform::setRect(&rc, 0, 0, _saveLoadImage->getWidth(), _saveLoadImage->getHeight()); - if (_loadInProgress) { - _saveLoadImage->displayTrans(_loadImageX, _loadImageY, rc); - } else { - _saveLoadImage->displayTrans(_saveImageX, _saveImageY, rc); - } - flip(); - _hasDrawnSaveLoadImage = true; - } - - if ((!_indicatorDisplay && _indicatorWidth <= 0) || _indicatorHeight <= 0) { - return STATUS_OK; - } - setupLines(); - int curWidth = (int)(_indicatorWidth * (float)((float)_indicatorProgress / 100.0f)); - for (int i = 0; i < _indicatorHeight; i++) { - drawLine(_indicatorX, _indicatorY + i, _indicatorX + curWidth, _indicatorY + i, _indicatorColor); - } - - setup2D(); - _indicatorWidthDrawn = curWidth; - if (_indicatorWidthDrawn) { - indicatorFlip(); - } - return STATUS_OK; -} - -} // end of namespace Wintermute +/* 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. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#include "engines/wintermute/base/base_active_rect.h" +#include "engines/wintermute/base/gfx/base_renderer.h" +#include "engines/wintermute/base/gfx/base_surface.h" +#include "engines/wintermute/base/base_sub_frame.h" +#include "engines/wintermute/base/base_region.h" +#include "engines/wintermute/platform_osystem.h" +#include "engines/wintermute/base/base_persistence_manager.h" + +namespace Wintermute { + +////////////////////////////////////////////////////////////////////// +BaseRenderer::BaseRenderer(BaseGame *inGame) : BaseClass(inGame) { + _window = 0; + _clipperWindow = 0; + _active = false; + _ready = false; + _windowed = true; + _forceAlphaColor = 0x00; + + _indicatorDisplay = false; + _indicatorColor = BYTETORGBA(255, 0, 0, 128); + _indicatorProgress = 0; + _indicatorX = -1; + _indicatorY = -1; + _indicatorWidth = -1; + _indicatorHeight = 8; + _indicatorWidthDrawn = 0; + + _loadImageName = ""; + _saveImageName = ""; + _saveLoadImage = NULL; + _loadInProgress = false; + _hasDrawnSaveLoadImage = false; + + _saveImageX = _saveImageY = 0; + _loadImageX = _loadImageY = 0; + + _width = _height = _bPP = 0; + BasePlatform::setRectEmpty(&_monitorRect); + + _realWidth = _realHeight = 0; + _drawOffsetX = _drawOffsetY = 0; +} + + +////////////////////////////////////////////////////////////////////// +BaseRenderer::~BaseRenderer() { + deleteRectList(); + unclipCursor(); + delete _saveLoadImage; +} + + +////////////////////////////////////////////////////////////////////// +void BaseRenderer::initLoop() { + deleteRectList(); +} + +void BaseRenderer::initIndicator() { + if (_indicatorY == -1) { + _indicatorY = _height - _indicatorHeight; + } + if (_indicatorX == -1) { + _indicatorX = 0; + } + if (_indicatorWidth == -1) { + _indicatorWidth = _width; + } +} + +void BaseRenderer::setIndicator(int width, int height, int x, int y, uint32 color) { + _indicatorWidth = width; + _indicatorHeight = height; + _indicatorX = x; + _indicatorY = y; + _indicatorColor = color; +} + +void BaseRenderer::setIndicatorVal(int value) { + bool redisplay = (_indicatorProgress != value); + _indicatorProgress = value; + if (redisplay) + displayIndicator(); +} + +void BaseRenderer::setLoadingScreen(const char *filename, int x, int y) { + // TODO: Handle NULL + _loadImageName = filename; + _loadImageX = x; + _loadImageY = y; +} + +void BaseRenderer::setSaveImage(const char *filename, int x, int y) { + // TODO: Handle NULL + _saveImageName = filename; + _saveImageX = x; + _saveImageY = y; +} + +void BaseRenderer::initSaveLoad(bool isSaving, bool quickSave) { + _indicatorDisplay = true; + _indicatorProgress = 0; + _hasDrawnSaveLoadImage = false; + + if (isSaving && !quickSave) { + delete _saveLoadImage; + _saveLoadImage = NULL; + if (_saveImageName.size()) { + _saveLoadImage = createSurface(); + + if (!_saveLoadImage || DID_FAIL(_saveLoadImage->create(_saveImageName, true, 0, 0, 0))) { + delete _saveLoadImage; + _saveLoadImage = NULL; + } + } + } else { + delete _saveLoadImage; + _saveLoadImage = NULL; + if (_loadImageName.size()) { + _saveLoadImage = createSurface(); + + if (!_saveLoadImage || DID_FAIL(_saveLoadImage->create(_loadImageName, true, 0, 0, 0))) { + delete _saveLoadImage; + _saveLoadImage = NULL; + } + } + _loadInProgress = true; + } +} + +void BaseRenderer::endSaveLoad() { + _loadInProgress = false; + _indicatorDisplay = false; + _indicatorWidthDrawn = 0; + + delete _saveLoadImage; + _saveLoadImage = NULL; +} + +void BaseRenderer::persistSaveLoadImages(BasePersistenceManager *persistMgr) { + persistMgr->transfer(TMEMBER(_loadImageName)); + persistMgr->transfer(TMEMBER(_saveImageName)); + persistMgr->transfer(TMEMBER(_saveImageX)); + persistMgr->transfer(TMEMBER(_saveImageY)); + persistMgr->transfer(TMEMBER(_loadImageX)); + persistMgr->transfer(TMEMBER(_loadImageY)); +} + +////////////////////////////////////////////////////////////////////// +BaseObject *BaseRenderer::getObjectAt(int x, int y) { + Point32 point; + point.x = x; + point.y = y; + + for (int i = _rectList.size() - 1; i >= 0; i--) { + if (BasePlatform::ptInRect(&_rectList[i]->_rect, point)) { + if (_rectList[i]->_precise) { + // frame + if (_rectList[i]->_frame) { + int xx = (int)((_rectList[i]->_frame->getRect().left + x - _rectList[i]->_rect.left + _rectList[i]->_offsetX) / (float)((float)_rectList[i]->_zoomX / (float)100)); + int yy = (int)((_rectList[i]->_frame->getRect().top + y - _rectList[i]->_rect.top + _rectList[i]->_offsetY) / (float)((float)_rectList[i]->_zoomY / (float)100)); + + if (_rectList[i]->_frame->_mirrorX) { + int width = _rectList[i]->_frame->getRect().right - _rectList[i]->_frame->getRect().left; + xx = width - xx; + } + + if (_rectList[i]->_frame->_mirrorY) { + int height = _rectList[i]->_frame->getRect().bottom - _rectList[i]->_frame->getRect().top; + yy = height - yy; + } + + if (!_rectList[i]->_frame->_surface->isTransparentAt(xx, yy)) { + return _rectList[i]->_owner; + } + } + // region + else if (_rectList[i]->_region) { + if (_rectList[i]->_region->pointInRegion(x + _rectList[i]->_offsetX, y + _rectList[i]->_offsetY)) { + return _rectList[i]->_owner; + } + } + } else { + return _rectList[i]->_owner; + } + } + } + + return (BaseObject *)NULL; +} + + +////////////////////////////////////////////////////////////////////////// +void BaseRenderer::deleteRectList() { + for (uint32 i = 0; i < _rectList.size(); i++) { + delete _rectList[i]; + } + _rectList.clear(); +} + +////////////////////////////////////////////////////////////////////// +bool BaseRenderer::initRenderer(int width, int height, bool windowed) { + return STATUS_FAILED; +} + + +////////////////////////////////////////////////////////////////////// +void BaseRenderer::onWindowChange() { +} + + +////////////////////////////////////////////////////////////////////////// +bool BaseRenderer::windowedBlt() { + return STATUS_FAILED; +} + + +////////////////////////////////////////////////////////////////////////// +bool BaseRenderer::setup2D(bool Force) { + return STATUS_FAILED; +} + + +////////////////////////////////////////////////////////////////////////// +bool BaseRenderer::setupLines() { + return STATUS_FAILED; +} + +////////////////////////////////////////////////////////////////////////// +bool BaseRenderer::drawLine(int x1, int y1, int x2, int y2, uint32 color) { + return STATUS_FAILED; +} + + +////////////////////////////////////////////////////////////////////////// +bool BaseRenderer::drawRect(int x1, int y1, int x2, int y2, uint32 color, int width) { + for (int i = 0; i < width; i++) { + drawLine(x1 + i, y1 + i, x2 - i, y1 + i, color); // up + drawLine(x1 + i, y2 - i, x2 - i + 1, y2 - i, color); // down + + drawLine(x1 + i, y1 + i, x1 + i, y2 - i, color); // left + drawLine(x2 - i, y1 + i, x2 - i, y2 - i + 1, color); // right + } + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool BaseRenderer::setViewport(int left, int top, int right, int bottom) { + return STATUS_FAILED; +} + + +////////////////////////////////////////////////////////////////////////// +bool BaseRenderer::setScreenViewport() { + return setViewport(_drawOffsetX, _drawOffsetY, _width + _drawOffsetX, _height + _drawOffsetY); +} + + +////////////////////////////////////////////////////////////////////////// +bool BaseRenderer::setViewport(Rect32 *rect) { + return setViewport(rect->left + _drawOffsetX, + rect->top + _drawOffsetY, + rect->right + _drawOffsetX, + rect->bottom + _drawOffsetY); +} + + +////////////////////////////////////////////////////////////////////////// +bool BaseRenderer::clipCursor() { + // TODO: Reimplement this. (Currently aspect-indpendence isn't quite finished) + /* + if (!_windowed) { + Rect32 rc; + GetWindowRect(_window, &rc); + + // if "maintain aspect ratio" is in effect, lock mouse to visible area + rc.left = _drawOffsetX; + rc.top = _drawOffsetY; + rc.right = rc.left + _width; + rc.bottom = rc.top + _height; + + ::ClipCursor(&rc); + } + */ + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +bool BaseRenderer::unclipCursor() { + /* + if (!_windowed) ::ClipCursor(NULL); + */ + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +bool BaseRenderer::pointInViewport(Point32 *p) { + if (p->x < _drawOffsetX) { + return false; + } + if (p->y < _drawOffsetY) { + return false; + } + if (p->x > _drawOffsetX + _width) { + return false; + } + if (p->y > _drawOffsetY + _height) { + return false; + } + + return true; +} + +void BaseRenderer::addRectToList(BaseActiveRect *rect) { + _rectList.push_back(rect); +} + +////////////////////////////////////////////////////////////////////////// +bool BaseRenderer::displayIndicator() { + if (!_indicatorDisplay || !_indicatorProgress) { + return STATUS_OK; + } + if (_saveLoadImage && !_hasDrawnSaveLoadImage) { + Rect32 rc; + BasePlatform::setRect(&rc, 0, 0, _saveLoadImage->getWidth(), _saveLoadImage->getHeight()); + if (_loadInProgress) { + _saveLoadImage->displayTrans(_loadImageX, _loadImageY, rc); + } else { + _saveLoadImage->displayTrans(_saveImageX, _saveImageY, rc); + } + flip(); + _hasDrawnSaveLoadImage = true; + } + + if ((!_indicatorDisplay && _indicatorWidth <= 0) || _indicatorHeight <= 0) { + return STATUS_OK; + } + setupLines(); + int curWidth = (int)(_indicatorWidth * (float)((float)_indicatorProgress / 100.0f)); + for (int i = 0; i < _indicatorHeight; i++) { + drawLine(_indicatorX, _indicatorY + i, _indicatorX + curWidth, _indicatorY + i, _indicatorColor); + } + + setup2D(); + _indicatorWidthDrawn = curWidth; + if (_indicatorWidthDrawn) { + indicatorFlip(); + } + return STATUS_OK; +} + +} // end of namespace Wintermute diff --git a/engines/wintermute/base/gfx/base_renderer.h b/engines/wintermute/base/gfx/base_renderer.h index 0ff4e6a3be..0475824464 100644 --- a/engines/wintermute/base/gfx/base_renderer.h +++ b/engines/wintermute/base/gfx/base_renderer.h @@ -1,221 +1,221 @@ -/* 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. - * - */ - -/* - * This file is based on WME Lite. - * http://dead-code.org/redir.php?target=wmelite - * Copyright (c) 2011 Jan Nedoma - */ - -#ifndef WINTERMUTE_BASE_RENDERER_H -#define WINTERMUTE_BASE_RENDERER_H - -#include "engines/wintermute/math/rect32.h" -#include "engines/wintermute/base/base.h" -#include "common/rect.h" -#include "common/array.h" - -namespace Wintermute { - -class BaseImage; -class BaseActiveRect; -class BaseObject; -class BaseSurface; -class BasePersistenceManager; - -/** - * @class BaseRenderer a common interface for the rendering portion of WME - * this interface is mainly intended to wrap away any differencies between - * software-rendering/hardware-rendering. - */ -class BaseRenderer: public BaseClass { -public: - int _realWidth; - int _realHeight; - int _drawOffsetX; - int _drawOffsetY; - - virtual void dumpData(const char *filename) {} - /** - * Take a screenshot of the current screenstate - * - * @return a BaseImage containing the current screen-buffer. - */ - virtual BaseImage *takeScreenshot() = 0; - virtual bool setViewport(int left, int top, int right, int bottom); - virtual bool setViewport(Rect32 *rect); - virtual Rect32 getViewPort() = 0; - virtual bool setScreenViewport(); - - virtual Graphics::PixelFormat getPixelFormat() const = 0; - /** - * Fade the screen to black - * - * @param alpha amount to fade by (alpha value of black) - * @return - */ - virtual void fade(uint16 alpha) = 0; - /** - * Fade a portion of the screen to a specific color - * - * @param r the red component to fade too. - * @param g the green component to fade too. - * @param b the blue component to fade too. - * @param a the alpha component to fade too. - * @param rect the portion of the screen to fade (if NULL, the entire screen will be faded). - */ - virtual void fadeToColor(byte r, byte g, byte b, byte a, Common::Rect *rect = NULL) = 0; - virtual bool drawLine(int x1, int y1, int x2, int y2, uint32 color); - virtual bool drawRect(int x1, int y1, int x2, int y2, uint32 color, int width = 1); - BaseRenderer(BaseGame *inGame = NULL); - virtual ~BaseRenderer(); - virtual bool setProjection() { - return STATUS_OK; - }; - - virtual bool windowedBlt(); - /** - * Fill a portion of the screen with a specified color - * - * @param r the red component to fill with. - * @param g the green component to fill with. - * @param b the blue component to fill with. - */ - virtual bool fill(byte r, byte g, byte b, Common::Rect *rect = NULL) = 0; - virtual void onWindowChange(); - virtual bool initRenderer(int width, int height, bool windowed); - /** - * Flip the backbuffer onto the screen-buffer - * The screen will NOT be updated before calling this function. - * - * @return true if successfull, false on error. - */ - virtual bool flip() = 0; - /** - * Special flip for the indicator drawn during save/load - * essentially, just copies the region defined by the _indicator-variables. - */ - virtual bool indicatorFlip() = 0; - virtual void initLoop(); - virtual bool setup2D(bool force = false); - virtual bool setupLines(); - - /** - * Get the name of the current renderer - * - * @return the name of the renderer. - */ - virtual Common::String getName() const = 0; - virtual bool displayDebugInfo() { - return STATUS_FAILED; - }; - virtual bool drawShaderQuad() { - return STATUS_FAILED; - } - - virtual float getScaleRatioX() const { - return 1.0f; - } - virtual float getScaleRatioY() const { - return 1.0f; - } - - /** - * Create a Surface fit for use with the renderer. - * As diverse implementations of BaseRenderer might have different solutions for storing surfaces - * this allows for a common interface for creating surface-handles. (Mostly usefull to ease future - * implementation of hw-accelerated rendering, or readding 3D-support at some point). - * - * @return a surface that can be used with this renderer - */ - virtual BaseSurface *createSurface() = 0; - - bool clipCursor(); - bool unclipCursor(); - - BaseObject *getObjectAt(int x, int y); - void deleteRectList(); - - virtual bool startSpriteBatch() { - return STATUS_OK; - }; - virtual bool endSpriteBatch() { - return STATUS_OK; - }; - bool pointInViewport(Point32 *P); - bool _active; - bool _ready; - bool _windowed; - int _bPP; - int _height; - int _width; - uint32 _window; - uint32 _forceAlphaColor; - - void addRectToList(BaseActiveRect *rect); - - // Indicator & Save/Load-related functions - void initIndicator(); - void setIndicatorVal(int value); - void setIndicator(int width, int height, int x, int y, uint32 color); - void persistSaveLoadImages(BasePersistenceManager *persistMgr); - void initSaveLoad(bool isSaving, bool quickSave = false); - void endSaveLoad(); - void setLoadingScreen(const char *filename, int x, int y); - void setSaveImage(const char *filename, int x, int y); - - bool displayIndicator(); -protected: - Common::String _loadImageName; - Common::String _saveImageName; - int _saveImageX; - int _saveImageY; - int _loadImageX; - int _loadImageY; - BaseSurface *_saveLoadImage; - bool _hasDrawnSaveLoadImage; - - int _indicatorWidthDrawn; - uint32 _indicatorColor; - int _indicatorX; - int _indicatorY; - int _indicatorWidth; - int _indicatorHeight; - bool _loadInProgress; - bool _indicatorDisplay; - int _indicatorProgress; -protected: - uint32 _clipperWindow; - - Rect32 _windowRect; - Rect32 _viewportRect; - Rect32 _screenRect; - Rect32 _monitorRect; -private: - Common::Array _rectList; -}; - -BaseRenderer *makeOSystemRenderer(BaseGame *inGame); // Implemented in BRenderSDL.cpp - -} // end of namespace Wintermute - -#endif +/* 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. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_BASE_RENDERER_H +#define WINTERMUTE_BASE_RENDERER_H + +#include "engines/wintermute/math/rect32.h" +#include "engines/wintermute/base/base.h" +#include "common/rect.h" +#include "common/array.h" + +namespace Wintermute { + +class BaseImage; +class BaseActiveRect; +class BaseObject; +class BaseSurface; +class BasePersistenceManager; + +/** + * @class BaseRenderer a common interface for the rendering portion of WME + * this interface is mainly intended to wrap away any differencies between + * software-rendering/hardware-rendering. + */ +class BaseRenderer: public BaseClass { +public: + int _realWidth; + int _realHeight; + int _drawOffsetX; + int _drawOffsetY; + + virtual void dumpData(const char *filename) {} + /** + * Take a screenshot of the current screenstate + * + * @return a BaseImage containing the current screen-buffer. + */ + virtual BaseImage *takeScreenshot() = 0; + virtual bool setViewport(int left, int top, int right, int bottom); + virtual bool setViewport(Rect32 *rect); + virtual Rect32 getViewPort() = 0; + virtual bool setScreenViewport(); + + virtual Graphics::PixelFormat getPixelFormat() const = 0; + /** + * Fade the screen to black + * + * @param alpha amount to fade by (alpha value of black) + * @return + */ + virtual void fade(uint16 alpha) = 0; + /** + * Fade a portion of the screen to a specific color + * + * @param r the red component to fade too. + * @param g the green component to fade too. + * @param b the blue component to fade too. + * @param a the alpha component to fade too. + * @param rect the portion of the screen to fade (if NULL, the entire screen will be faded). + */ + virtual void fadeToColor(byte r, byte g, byte b, byte a, Common::Rect *rect = NULL) = 0; + virtual bool drawLine(int x1, int y1, int x2, int y2, uint32 color); + virtual bool drawRect(int x1, int y1, int x2, int y2, uint32 color, int width = 1); + BaseRenderer(BaseGame *inGame = NULL); + virtual ~BaseRenderer(); + virtual bool setProjection() { + return STATUS_OK; + }; + + virtual bool windowedBlt(); + /** + * Fill a portion of the screen with a specified color + * + * @param r the red component to fill with. + * @param g the green component to fill with. + * @param b the blue component to fill with. + */ + virtual bool fill(byte r, byte g, byte b, Common::Rect *rect = NULL) = 0; + virtual void onWindowChange(); + virtual bool initRenderer(int width, int height, bool windowed); + /** + * Flip the backbuffer onto the screen-buffer + * The screen will NOT be updated before calling this function. + * + * @return true if successfull, false on error. + */ + virtual bool flip() = 0; + /** + * Special flip for the indicator drawn during save/load + * essentially, just copies the region defined by the _indicator-variables. + */ + virtual bool indicatorFlip() = 0; + virtual void initLoop(); + virtual bool setup2D(bool force = false); + virtual bool setupLines(); + + /** + * Get the name of the current renderer + * + * @return the name of the renderer. + */ + virtual Common::String getName() const = 0; + virtual bool displayDebugInfo() { + return STATUS_FAILED; + }; + virtual bool drawShaderQuad() { + return STATUS_FAILED; + } + + virtual float getScaleRatioX() const { + return 1.0f; + } + virtual float getScaleRatioY() const { + return 1.0f; + } + + /** + * Create a Surface fit for use with the renderer. + * As diverse implementations of BaseRenderer might have different solutions for storing surfaces + * this allows for a common interface for creating surface-handles. (Mostly usefull to ease future + * implementation of hw-accelerated rendering, or readding 3D-support at some point). + * + * @return a surface that can be used with this renderer + */ + virtual BaseSurface *createSurface() = 0; + + bool clipCursor(); + bool unclipCursor(); + + BaseObject *getObjectAt(int x, int y); + void deleteRectList(); + + virtual bool startSpriteBatch() { + return STATUS_OK; + }; + virtual bool endSpriteBatch() { + return STATUS_OK; + }; + bool pointInViewport(Point32 *P); + bool _active; + bool _ready; + bool _windowed; + int _bPP; + int _height; + int _width; + uint32 _window; + uint32 _forceAlphaColor; + + void addRectToList(BaseActiveRect *rect); + + // Indicator & Save/Load-related functions + void initIndicator(); + void setIndicatorVal(int value); + void setIndicator(int width, int height, int x, int y, uint32 color); + void persistSaveLoadImages(BasePersistenceManager *persistMgr); + void initSaveLoad(bool isSaving, bool quickSave = false); + void endSaveLoad(); + void setLoadingScreen(const char *filename, int x, int y); + void setSaveImage(const char *filename, int x, int y); + + bool displayIndicator(); +protected: + Common::String _loadImageName; + Common::String _saveImageName; + int _saveImageX; + int _saveImageY; + int _loadImageX; + int _loadImageY; + BaseSurface *_saveLoadImage; + bool _hasDrawnSaveLoadImage; + + int _indicatorWidthDrawn; + uint32 _indicatorColor; + int _indicatorX; + int _indicatorY; + int _indicatorWidth; + int _indicatorHeight; + bool _loadInProgress; + bool _indicatorDisplay; + int _indicatorProgress; +protected: + uint32 _clipperWindow; + + Rect32 _windowRect; + Rect32 _viewportRect; + Rect32 _screenRect; + Rect32 _monitorRect; +private: + Common::Array _rectList; +}; + +BaseRenderer *makeOSystemRenderer(BaseGame *inGame); // Implemented in BRenderSDL.cpp + +} // end of namespace Wintermute + +#endif diff --git a/engines/wintermute/base/gfx/base_surface.cpp b/engines/wintermute/base/gfx/base_surface.cpp index cbd665591a..d882adf5ad 100644 --- a/engines/wintermute/base/gfx/base_surface.cpp +++ b/engines/wintermute/base/gfx/base_surface.cpp @@ -1,149 +1,149 @@ -/* 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. - * - */ - -/* - * This file is based on WME Lite. - * http://dead-code.org/redir.php?target=wmelite - * Copyright (c) 2011 Jan Nedoma - */ - -#include "engines/wintermute/wintypes.h" -#include "engines/wintermute/base/base_game.h" -#include "engines/wintermute/base/gfx/base_surface.h" - -namespace Wintermute { - -////////////////////////////////////////////////////////////////////// -BaseSurface::BaseSurface(BaseGame *inGame) : BaseClass(inGame) { - _referenceCount = 0; - - _width = _height = 0; - - _filename = ""; - - _pixelOpReady = false; - - _ckDefault = true; - _ckRed = _ckGreen = _ckBlue = 0; - _lifeTime = 0; - _keepLoaded = false; - - _lastUsedTime = 0; - _valid = false; -} - - -////////////////////////////////////////////////////////////////////// -BaseSurface::~BaseSurface() { - if (_pixelOpReady) { - endPixelOp(); - } -} - -////////////////////////////////////////////////////////////////////// -bool BaseSurface::restore() { - return STATUS_FAILED; -} - -////////////////////////////////////////////////////////////////////// -bool BaseSurface::isTransparentAt(int x, int y) { - return false; -} - -////////////////////////////////////////////////////////////////////// -bool BaseSurface::displayHalfTrans(int x, int y, Rect32 rect) { - return STATUS_FAILED; -} - -////////////////////////////////////////////////////////////////////////// -bool BaseSurface::displayTransform(int x, int y, int hotX, int hotY, Rect32 rect, float zoomX, float zoomY, uint32 alpha, float rotate, TSpriteBlendMode blendMode, bool mirrorX, bool mirrorY) { - return displayTransZoom(x, y, rect, zoomX, zoomY, alpha, blendMode, mirrorX, mirrorY); -} - -////////////////////////////////////////////////////////////////////////// -bool BaseSurface::create(int width, int height) { - return STATUS_FAILED; -} - - -////////////////////////////////////////////////////////////////////////// -bool BaseSurface::startPixelOp() { - return STATUS_FAILED; -} - -////////////////////////////////////////////////////////////////////////// -bool BaseSurface::endPixelOp() { - return STATUS_FAILED; -} - - -////////////////////////////////////////////////////////////////////////// -bool BaseSurface::getPixel(int x, int y, byte *r, byte *g, byte *b, byte *a) { - return STATUS_FAILED; -} - - -////////////////////////////////////////////////////////////////////////// -bool BaseSurface::putPixel(int x, int y, byte r, byte g, byte b, int a) { - return STATUS_FAILED; -} - - -////////////////////////////////////////////////////////////////////////// -bool BaseSurface::comparePixel(int x, int y, byte r, byte g, byte b, int a) { - return false; -} - - -////////////////////////////////////////////////////////////////////// -bool BaseSurface::isTransparentAtLite(int x, int y) { - return false; -} - - -////////////////////////////////////////////////////////////////////////// -bool BaseSurface::invalidate() { - return STATUS_FAILED; -} - - - -////////////////////////////////////////////////////////////////////////// -bool BaseSurface::prepareToDraw() { - _lastUsedTime = _gameRef->_liveTimer; - - if (!_valid) { - //_gameRef->LOG(0, "Reviving: %s", _filename); - return create(_filename.c_str(), _ckDefault, _ckRed, _ckGreen, _ckBlue, _lifeTime, _keepLoaded); - } else { - return STATUS_OK; - } -} - - -////////////////////////////////////////////////////////////////////////// -void BaseSurface::setSize(int width, int height) { - _width = width; - _height = height; -} - -} // end of namespace Wintermute +/* 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. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#include "engines/wintermute/wintypes.h" +#include "engines/wintermute/base/base_game.h" +#include "engines/wintermute/base/gfx/base_surface.h" + +namespace Wintermute { + +////////////////////////////////////////////////////////////////////// +BaseSurface::BaseSurface(BaseGame *inGame) : BaseClass(inGame) { + _referenceCount = 0; + + _width = _height = 0; + + _filename = ""; + + _pixelOpReady = false; + + _ckDefault = true; + _ckRed = _ckGreen = _ckBlue = 0; + _lifeTime = 0; + _keepLoaded = false; + + _lastUsedTime = 0; + _valid = false; +} + + +////////////////////////////////////////////////////////////////////// +BaseSurface::~BaseSurface() { + if (_pixelOpReady) { + endPixelOp(); + } +} + +////////////////////////////////////////////////////////////////////// +bool BaseSurface::restore() { + return STATUS_FAILED; +} + +////////////////////////////////////////////////////////////////////// +bool BaseSurface::isTransparentAt(int x, int y) { + return false; +} + +////////////////////////////////////////////////////////////////////// +bool BaseSurface::displayHalfTrans(int x, int y, Rect32 rect) { + return STATUS_FAILED; +} + +////////////////////////////////////////////////////////////////////////// +bool BaseSurface::displayTransform(int x, int y, int hotX, int hotY, Rect32 rect, float zoomX, float zoomY, uint32 alpha, float rotate, TSpriteBlendMode blendMode, bool mirrorX, bool mirrorY) { + return displayTransZoom(x, y, rect, zoomX, zoomY, alpha, blendMode, mirrorX, mirrorY); +} + +////////////////////////////////////////////////////////////////////////// +bool BaseSurface::create(int width, int height) { + return STATUS_FAILED; +} + + +////////////////////////////////////////////////////////////////////////// +bool BaseSurface::startPixelOp() { + return STATUS_FAILED; +} + +////////////////////////////////////////////////////////////////////////// +bool BaseSurface::endPixelOp() { + return STATUS_FAILED; +} + + +////////////////////////////////////////////////////////////////////////// +bool BaseSurface::getPixel(int x, int y, byte *r, byte *g, byte *b, byte *a) { + return STATUS_FAILED; +} + + +////////////////////////////////////////////////////////////////////////// +bool BaseSurface::putPixel(int x, int y, byte r, byte g, byte b, int a) { + return STATUS_FAILED; +} + + +////////////////////////////////////////////////////////////////////////// +bool BaseSurface::comparePixel(int x, int y, byte r, byte g, byte b, int a) { + return false; +} + + +////////////////////////////////////////////////////////////////////// +bool BaseSurface::isTransparentAtLite(int x, int y) { + return false; +} + + +////////////////////////////////////////////////////////////////////////// +bool BaseSurface::invalidate() { + return STATUS_FAILED; +} + + + +////////////////////////////////////////////////////////////////////////// +bool BaseSurface::prepareToDraw() { + _lastUsedTime = _gameRef->_liveTimer; + + if (!_valid) { + //_gameRef->LOG(0, "Reviving: %s", _filename); + return create(_filename.c_str(), _ckDefault, _ckRed, _ckGreen, _ckBlue, _lifeTime, _keepLoaded); + } else { + return STATUS_OK; + } +} + + +////////////////////////////////////////////////////////////////////////// +void BaseSurface::setSize(int width, int height) { + _width = width; + _height = height; +} + +} // end of namespace Wintermute diff --git a/engines/wintermute/base/gfx/base_surface.h b/engines/wintermute/base/gfx/base_surface.h index f45856f652..ee53c03e77 100644 --- a/engines/wintermute/base/gfx/base_surface.h +++ b/engines/wintermute/base/gfx/base_surface.h @@ -1,99 +1,99 @@ -/* 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. - * - */ - -/* - * This file is based on WME Lite. - * http://dead-code.org/redir.php?target=wmelite - * Copyright (c) 2011 Jan Nedoma - */ - -#ifndef WINTERMUTE_BASE_SURFACE_H -#define WINTERMUTE_BASE_SURFACE_H - -#include "engines/wintermute/base/base.h" -#include "engines/wintermute/math/rect32.h" -#include "graphics/surface.h" - -namespace Wintermute { - -class BaseSurface: public BaseClass { -public: - virtual bool invalidate(); - virtual bool prepareToDraw(); - uint32 _lastUsedTime; - bool _valid; - int _lifeTime; - - bool _pixelOpReady; - BaseSurface(BaseGame *inGame); - virtual ~BaseSurface(); - - virtual bool displayHalfTrans(int x, int y, Rect32 rect); - virtual bool isTransparentAt(int x, int y); - virtual bool displayTransZoom(int x, int y, Rect32 rect, float zoomX, float zoomY, uint32 alpha = 0xFFFFFFFF, TSpriteBlendMode blendMode = BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false) = 0; - virtual bool displayTrans(int x, int y, Rect32 rect, uint32 alpha = 0xFFFFFFFF, TSpriteBlendMode blendMode = BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false) = 0; - virtual bool displayTransOffset(int x, int y, Rect32 rect, uint32 alpha = 0xFFFFFFFF, TSpriteBlendMode blendMode = BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false, int offsetX = 0, int offsetY = 0) = 0; - virtual bool display(int x, int y, Rect32 rect, TSpriteBlendMode blendMode = BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false) = 0; - virtual bool displayZoom(int x, int y, Rect32 rect, float zoomX, float zoomY, uint32 alpha = 0xFFFFFFFF, bool transparent = false, TSpriteBlendMode blendMode = BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false) = 0; - virtual bool displayTransform(int x, int y, int hotX, int hotY, Rect32 rect, float zoomX, float zoomY, uint32 alpha, float rotate, TSpriteBlendMode blendMode = BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false) = 0; - virtual bool restore(); - virtual bool create(const Common::String &filename, bool defaultCK, byte ckRed, byte ckGreen, byte ckBlue, int lifeTime = -1, bool keepLoaded = false) = 0; - virtual bool create(int width, int height); - virtual bool putSurface(const Graphics::Surface &surface, bool hasAlpha = false) { - return STATUS_FAILED; - } - virtual bool putPixel(int x, int y, byte r, byte g, byte b, int a = -1); - virtual bool getPixel(int x, int y, byte *r, byte *g, byte *b, byte *a = NULL); - virtual bool comparePixel(int x, int y, byte r, byte g, byte b, int a = -1); - virtual bool startPixelOp(); - virtual bool endPixelOp(); - virtual bool isTransparentAtLite(int x, int y); - void setSize(int width, int height); - - int _referenceCount; - - virtual int getWidth() { - return _width; - } - virtual int getHeight() { - return _height; - } - Common::String getFileNameStr() { return _filename; } - const char* getFileName() { return _filename.c_str(); } - //void SetWidth(int Width){ _width = Width; } - //void SetHeight(int Height){ _height = Height; } -protected: - bool _ckDefault; - byte _ckRed; - byte _ckGreen; - byte _ckBlue; - - bool _keepLoaded; - Common::String _filename; - int _height; - int _width; - -}; - -} // end of namespace Wintermute - -#endif +/* 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. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_BASE_SURFACE_H +#define WINTERMUTE_BASE_SURFACE_H + +#include "engines/wintermute/base/base.h" +#include "engines/wintermute/math/rect32.h" +#include "graphics/surface.h" + +namespace Wintermute { + +class BaseSurface: public BaseClass { +public: + virtual bool invalidate(); + virtual bool prepareToDraw(); + uint32 _lastUsedTime; + bool _valid; + int _lifeTime; + + bool _pixelOpReady; + BaseSurface(BaseGame *inGame); + virtual ~BaseSurface(); + + virtual bool displayHalfTrans(int x, int y, Rect32 rect); + virtual bool isTransparentAt(int x, int y); + virtual bool displayTransZoom(int x, int y, Rect32 rect, float zoomX, float zoomY, uint32 alpha = 0xFFFFFFFF, TSpriteBlendMode blendMode = BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false) = 0; + virtual bool displayTrans(int x, int y, Rect32 rect, uint32 alpha = 0xFFFFFFFF, TSpriteBlendMode blendMode = BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false) = 0; + virtual bool displayTransOffset(int x, int y, Rect32 rect, uint32 alpha = 0xFFFFFFFF, TSpriteBlendMode blendMode = BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false, int offsetX = 0, int offsetY = 0) = 0; + virtual bool display(int x, int y, Rect32 rect, TSpriteBlendMode blendMode = BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false) = 0; + virtual bool displayZoom(int x, int y, Rect32 rect, float zoomX, float zoomY, uint32 alpha = 0xFFFFFFFF, bool transparent = false, TSpriteBlendMode blendMode = BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false) = 0; + virtual bool displayTransform(int x, int y, int hotX, int hotY, Rect32 rect, float zoomX, float zoomY, uint32 alpha, float rotate, TSpriteBlendMode blendMode = BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false) = 0; + virtual bool restore(); + virtual bool create(const Common::String &filename, bool defaultCK, byte ckRed, byte ckGreen, byte ckBlue, int lifeTime = -1, bool keepLoaded = false) = 0; + virtual bool create(int width, int height); + virtual bool putSurface(const Graphics::Surface &surface, bool hasAlpha = false) { + return STATUS_FAILED; + } + virtual bool putPixel(int x, int y, byte r, byte g, byte b, int a = -1); + virtual bool getPixel(int x, int y, byte *r, byte *g, byte *b, byte *a = NULL); + virtual bool comparePixel(int x, int y, byte r, byte g, byte b, int a = -1); + virtual bool startPixelOp(); + virtual bool endPixelOp(); + virtual bool isTransparentAtLite(int x, int y); + void setSize(int width, int height); + + int _referenceCount; + + virtual int getWidth() { + return _width; + } + virtual int getHeight() { + return _height; + } + Common::String getFileNameStr() { return _filename; } + const char* getFileName() { return _filename.c_str(); } + //void SetWidth(int Width){ _width = Width; } + //void SetHeight(int Height){ _height = Height; } +protected: + bool _ckDefault; + byte _ckRed; + byte _ckGreen; + byte _ckBlue; + + bool _keepLoaded; + Common::String _filename; + int _height; + int _width; + +}; + +} // end of namespace Wintermute + +#endif diff --git a/engines/wintermute/base/gfx/osystem/base_render_osystem.cpp b/engines/wintermute/base/gfx/osystem/base_render_osystem.cpp index 7a862e4441..6d67253038 100644 --- a/engines/wintermute/base/gfx/osystem/base_render_osystem.cpp +++ b/engines/wintermute/base/gfx/osystem/base_render_osystem.cpp @@ -1,604 +1,604 @@ -/* 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. - * - */ - -/* - * This file is based on WME Lite. - * http://dead-code.org/redir.php?target=wmelite - * Copyright (c) 2011 Jan Nedoma - */ - -#include "engines/wintermute/base/gfx/osystem/base_render_osystem.h" -#include "engines/wintermute/base/gfx/osystem/base_surface_osystem.h" -#include "engines/wintermute/base/base_surface_storage.h" -#include "engines/wintermute/base/gfx/base_image.h" -#include "engines/wintermute/math/math_util.h" -#include "engines/wintermute/base/base_game.h" -#include "engines/wintermute/base/base_sprite.h" -#include "common/system.h" -#include "engines/wintermute/graphics/transparent_surface.h" -#include "common/queue.h" -#include "common/config-manager.h" - -namespace Wintermute { - -RenderTicket::RenderTicket(BaseSurfaceOSystem *owner, const Graphics::Surface *surf, Common::Rect *srcRect, Common::Rect *dstRect, bool mirrorX, bool mirrorY, bool disableAlpha) : _owner(owner), - _srcRect(*srcRect), _dstRect(*dstRect), _drawNum(0), _isValid(true), _wantsDraw(true), _hasAlpha(!disableAlpha) { - _colorMod = 0; - _mirror = TransparentSurface::FLIP_NONE; - if (mirrorX) { - _mirror |= TransparentSurface::FLIP_V; - } - if (mirrorY) { - _mirror |= TransparentSurface::FLIP_H; - } - if (surf) { - _surface = new Graphics::Surface(); - _surface->create((uint16)srcRect->width(), (uint16)srcRect->height(), surf->format); - assert(_surface->format.bytesPerPixel == 4); - // Get a clipped copy of the surface - for (int i = 0; i < _surface->h; i++) { - memcpy(_surface->getBasePtr(0, i), surf->getBasePtr(srcRect->left, srcRect->top + i), srcRect->width() * _surface->format.bytesPerPixel); - } - // Then scale it if necessary - if (dstRect->width() != srcRect->width() || dstRect->height() != srcRect->height()) { - TransparentSurface src(*_surface, false); - Graphics::Surface *temp = src.scale(dstRect->width(), dstRect->height()); - _surface->free(); - delete _surface; - _surface = temp; - } - } else { - _surface = NULL; - } -} - -RenderTicket::~RenderTicket() { - if (_surface) { - _surface->free(); - delete _surface; - } -} - -bool RenderTicket::operator==(RenderTicket &t) { - if ((t._srcRect != _srcRect) || - (t._dstRect != _dstRect) || - (t._mirror != _mirror) || - (t._owner != _owner) || - (t._hasAlpha != _hasAlpha) || - (t._colorMod != _colorMod)) { - return false; - } - return true; -} - -BaseRenderer *makeOSystemRenderer(BaseGame *inGame) { - return new BaseRenderOSystem(inGame); -} - -////////////////////////////////////////////////////////////////////////// -BaseRenderOSystem::BaseRenderOSystem(BaseGame *inGame) : BaseRenderer(inGame) { - _renderSurface = new Graphics::Surface(); - _blankSurface = new Graphics::Surface(); - _drawNum = 1; - _needsFlip = true; - - _borderLeft = _borderRight = _borderTop = _borderBottom = 0; - _ratioX = _ratioY = 1.0f; - setAlphaMod(255); - setColorMod(255, 255, 255); - _dirtyRect = NULL; -} - -////////////////////////////////////////////////////////////////////////// -BaseRenderOSystem::~BaseRenderOSystem() { - _renderSurface->free(); - delete _renderSurface; - _blankSurface->free(); - delete _blankSurface; - TransparentSurface::destroyLookup(); -} - -////////////////////////////////////////////////////////////////////////// -bool BaseRenderOSystem::initRenderer(int width, int height, bool windowed) { - _width = width; - _height = height; - _renderRect.setWidth(_width); - _renderRect.setHeight(_height); - - _realWidth = width; - _realHeight = height; - - //TODO: Tiny resolution-displays might want to do some resolution-selection logic here - - //_realWidth = BaseEngine::instance().getRegistry()->readInt("Debug", "ForceResWidth", _width); - //_realHeight = BaseEngine::instance().getRegistry()->readInt("Debug", "ForceResHeight", _height); - - float origAspect = (float)_width / (float)_height; - float realAspect = (float)_realWidth / (float)_realHeight; - - float ratio; - if (origAspect < realAspect) { - // normal to wide - ratio = (float)_realHeight / (float)_height; - } else { - // wide to normal - ratio = (float)_realWidth / (float)_width; - } - - _borderLeft = (int)((_realWidth - (_width * ratio)) / 2); - _borderRight = (int)(_realWidth - (_width * ratio) - _borderLeft); - - _borderTop = (int)((_realHeight - (_height * ratio)) / 2); - _borderBottom = (int)(_realHeight - (_height * ratio) - _borderTop); - - - - _ratioX = (float)(_realWidth - _borderLeft - _borderRight) / (float)_width; - _ratioY = (float)(_realHeight - _borderTop - _borderBottom) / (float)_height; - - _windowed = !ConfMan.getBool("fullscreen"); - - Graphics::PixelFormat format(4, 8, 8, 8, 8, 16, 8, 0, 24); - g_system->beginGFXTransaction(); - g_system->initSize(_width, _height, &format); - OSystem::TransactionError gfxError = g_system->endGFXTransaction(); - - if (gfxError != OSystem::kTransactionSuccess) { - warning("Couldn't setup GFX-backend for %dx%dx%d", _width, _height, format.bytesPerPixel * 8); - return STATUS_FAILED; - } - - g_system->showMouse(false); - - _renderSurface->create(g_system->getWidth(), g_system->getHeight(), g_system->getScreenFormat()); - _blankSurface->create(g_system->getWidth(), g_system->getHeight(), g_system->getScreenFormat()); - _blankSurface->fillRect(Common::Rect(0, 0, _blankSurface->h, _blankSurface->w), _blankSurface->format.ARGBToColor(255, 0, 0, 0)); - _active = true; - - _clearColor = _renderSurface->format.ARGBToColor(255, 0, 0, 0); - - return STATUS_OK; -} - -void BaseRenderOSystem::setAlphaMod(byte alpha) { - byte r = RGBCOLGetR(_colorMod); - byte g = RGBCOLGetB(_colorMod); - byte b = RGBCOLGetB(_colorMod); - _colorMod = BS_ARGB(alpha, r, g, b); -} - -void BaseRenderOSystem::setColorMod(byte r, byte g, byte b) { - byte alpha = RGBCOLGetA(_colorMod); - _colorMod = BS_ARGB(alpha, r, g, b); -} - -bool BaseRenderOSystem::indicatorFlip() { - g_system->copyRectToScreen((byte *)_renderSurface->getBasePtr(_indicatorX, _indicatorY), _renderSurface->pitch, _indicatorX, _indicatorY, _indicatorWidthDrawn, _indicatorHeight); - g_system->updateScreen(); - return STATUS_OK; -} - -bool BaseRenderOSystem::flip() { - if (!_disableDirtyRects) { - drawTickets(); - } else { - // Clear the scale-buffered tickets that wasn't reused. - RenderQueueIterator it = _renderQueue.begin(); - while (it != _renderQueue.end()) { - if ((*it)->_wantsDraw == false) { - RenderTicket *ticket = *it; - it = _renderQueue.erase(it); - delete ticket; - } else { - (*it)->_wantsDraw = false; - ++it; - } - } - } - if (_needsFlip || _disableDirtyRects) { - if (_disableDirtyRects) { - g_system->copyRectToScreen((byte *)_renderSurface->pixels, _renderSurface->pitch, 0, 0, _renderSurface->w, _renderSurface->h); - } - // g_system->copyRectToScreen((byte *)_renderSurface->pixels, _renderSurface->pitch, _dirtyRect->left, _dirtyRect->top, _dirtyRect->width(), _dirtyRect->height()); - delete _dirtyRect; - _dirtyRect = NULL; - g_system->updateScreen(); - _needsFlip = false; - } - _drawNum = 1; - - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -bool BaseRenderOSystem::fill(byte r, byte g, byte b, Common::Rect *rect) { - _clearColor = _renderSurface->format.ARGBToColor(0xFF, r, g, b); - if (!_disableDirtyRects) { - return STATUS_OK; - } - if (!rect) { -// TODO: This should speed things up, but for some reason it misses the size by quite a bit. -/* if (r == 0 && g == 0 && b == 0) { - // Simply memcpy from the buffered black-surface, way faster than Surface::fillRect. - memcpy(_renderSurface->pixels, _blankSurface->pixels, _renderSurface->pitch * _renderSurface->h); - return STATUS_OK; - }*/ - rect = &_renderRect; - } - // TODO: This doesn't work with dirty rects - _renderSurface->fillRect(*rect, _clearColor); - - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -void BaseRenderOSystem::fade(uint16 alpha) { - byte dwAlpha = (byte)(255 - alpha); - return fadeToColor(0, 0, 0, dwAlpha); -} - - -////////////////////////////////////////////////////////////////////////// -void BaseRenderOSystem::fadeToColor(byte r, byte g, byte b, byte a, Common::Rect *rect) { - // This particular warning is rather messy, as this function is called a ton, - // thus we avoid printing it more than once. - - // TODO: Add fading with dirty rects. - if (!_disableDirtyRects) { - warning("BaseRenderOSystem::FadeToColor - Breaks when using dirty rects"); - } - - Common::Rect fillRect; - - if (rect) { - fillRect.left = rect->left; - fillRect.top = rect->top; - fillRect.setWidth(rect->width()); - fillRect.setHeight(rect->height()); - } else { - Rect32 rc; - _gameRef->getCurrentViewportRect(&rc); - fillRect.left = (int16)rc.left; - fillRect.top = (int16)rc.top; - fillRect.setWidth((int16)(rc.right - rc.left)); - fillRect.setHeight((int16)(rc.bottom - rc.top)); - } - modTargetRect(&fillRect); - - //TODO: This is only here until I'm sure about the final pixelformat - uint32 col = _renderSurface->format.ARGBToColor(a, r, g, b); - - setAlphaMod(255); - setColorMod(255, 255, 255); - Graphics::Surface surf; - surf.create((uint16)fillRect.width(), (uint16)fillRect.height(), _renderSurface->format); - Common::Rect sizeRect(fillRect); - sizeRect.translate(-fillRect.top, -fillRect.left); - surf.fillRect(fillRect, col); - drawSurface(NULL, &surf, &sizeRect, &fillRect, false, false); - surf.free(); - - //SDL_SetRenderDrawColor(_renderer, r, g, b, a); - //SDL_SetRenderDrawBlendMode(_renderer, SDL_BLENDMODE_BLEND); - //SDL_RenderFillRect(_renderer, &fillRect); -} - -Graphics::PixelFormat BaseRenderOSystem::getPixelFormat() const { - return _renderSurface->format; -} - -void BaseRenderOSystem::drawSurface(BaseSurfaceOSystem *owner, const Graphics::Surface *surf, Common::Rect *srcRect, Common::Rect *dstRect, bool mirrorX, bool mirrorY, bool disableAlpha) { - // Skip rects that are completely outside the screen: - if ((dstRect->left < 0 && dstRect->right < 0) || (dstRect->top < 0 && dstRect->bottom < 0)) { - return; - } - - if (owner) { // Fade-tickets are owner-less - RenderTicket compare(owner, NULL, srcRect, dstRect, mirrorX, mirrorY, disableAlpha); - compare._colorMod = _colorMod; - RenderQueueIterator it; - for (it = _renderQueue.begin(); it != _renderQueue.end(); ++it) { - if ((*it)->_owner == owner && *(*it) == compare && (*it)->_isValid) { - (*it)->_colorMod = _colorMod; - if (_disableDirtyRects) { - drawFromSurface(*it, NULL); - } else { - drawFromTicket(*it); - } - return; - } - } - } - RenderTicket *ticket = new RenderTicket(owner, surf, srcRect, dstRect, mirrorX, mirrorY, disableAlpha); - ticket->_colorMod = _colorMod; - if (!_disableDirtyRects) { - drawFromTicket(ticket); - } else { - ticket->_wantsDraw = true; - _renderQueue.push_back(ticket); - drawFromSurface(ticket, NULL); - } -} - -void BaseRenderOSystem::invalidateTicket(RenderTicket *renderTicket) { - addDirtyRect(renderTicket->_dstRect); - renderTicket->_isValid = false; -// renderTicket->_canDelete = true; // TODO: Maybe readd this, to avoid even more duplicates. -} - -void BaseRenderOSystem::invalidateTicketsFromSurface(BaseSurfaceOSystem *surf) { - RenderQueueIterator it; - for (it = _renderQueue.begin(); it != _renderQueue.end(); ++it) { - if ((*it)->_owner == surf) { - invalidateTicket(*it); - } - } -} - -void BaseRenderOSystem::drawFromTicket(RenderTicket *renderTicket) { - renderTicket->_wantsDraw = true; - // A new item always has _drawNum == 0 - if (renderTicket->_drawNum == 0) { - // In-order - if (_renderQueue.empty() || _drawNum > (_renderQueue.back())->_drawNum) { - renderTicket->_drawNum = _drawNum++; - _renderQueue.push_back(renderTicket); - addDirtyRect(renderTicket->_dstRect); - } else { - // Before something - Common::List::iterator pos; - for (pos = _renderQueue.begin(); pos != _renderQueue.end(); pos++) { - if ((*pos)->_drawNum >= _drawNum) { - break; - } - } - _renderQueue.insert(pos, renderTicket); - Common::List::iterator it; - renderTicket->_drawNum = _drawNum++; - // Increment the following tickets, so they still are in line - for (it = pos; it != _renderQueue.end(); ++it) { - (*it)->_drawNum++; - (*it)->_wantsDraw = false; - } - addDirtyRect(renderTicket->_dstRect); - } - } else { - // Was drawn last round, still in the same order - if (_drawNum == renderTicket->_drawNum) { - _drawNum++; - } else { - // Remove the ticket from the list - RenderQueueIterator it = _renderQueue.begin(); - while (it != _renderQueue.end()) { - if ((*it) == renderTicket) { - it = _renderQueue.erase(it); - break; - } else { - ++it; - } - } - if (it != _renderQueue.end()) { - // Decreement the following tickets. - for (; it != _renderQueue.end(); ++it) { - (*it)->_drawNum--; - } - } - // Is not in order, so readd it as if it was a new ticket - renderTicket->_drawNum = 0; - drawFromTicket(renderTicket); - } - } -} - -void BaseRenderOSystem::addDirtyRect(const Common::Rect &rect) { - if (!_dirtyRect) { - _dirtyRect = new Common::Rect(rect); - } else { - _dirtyRect->extend(rect); - } - _dirtyRect->clip(_renderRect); -} - -void BaseRenderOSystem::drawTickets() { - RenderQueueIterator it = _renderQueue.begin(); - // Clean out the old tickets - int decrement = 0; - while (it != _renderQueue.end()) { - if ((*it)->_wantsDraw == false || (*it)->_isValid == false) { - RenderTicket *ticket = *it; - addDirtyRect((*it)->_dstRect); - it = _renderQueue.erase(it); - delete ticket; - decrement++; - } else { - (*it)->_drawNum -= decrement; - ++it; - } - } - if (!_dirtyRect || _dirtyRect->width() == 0 || _dirtyRect->height() == 0) { - return; - } - // The color-mods are stored in the RenderTickets on add, since we set that state again during - // draw, we need to keep track of what it was prior to draw. - uint32 oldColorMod = _colorMod; - - // Apply the clear-color to the dirty rect. - _renderSurface->fillRect(*_dirtyRect, _clearColor); - _drawNum = 1; - for (it = _renderQueue.begin(); it != _renderQueue.end(); ++it) { - RenderTicket *ticket = *it; - assert(ticket->_drawNum == _drawNum++); - if (ticket->_isValid && ticket->_dstRect.intersects(*_dirtyRect)) { - // dstClip is the area we want redrawn. - Common::Rect dstClip(ticket->_dstRect); - // reduce it to the dirty rect - dstClip.clip(*_dirtyRect); - // we need to keep track of the position to redraw the dirty rect - Common::Rect pos(dstClip); - int16 offsetX = ticket->_dstRect.left; - int16 offsetY = ticket->_dstRect.top; - // convert from screen-coords to surface-coords. - dstClip.translate(-offsetX, -offsetY); - - _colorMod = ticket->_colorMod; - drawFromSurface(ticket->getSurface(), &ticket->_srcRect, &pos, &dstClip, ticket->_mirror); - _needsFlip = true; - } - // Some tickets want redraw but don't actually clip the dirty area (typically the ones that shouldnt become clear-color) - ticket->_wantsDraw = false; - } - g_system->copyRectToScreen((byte *)_renderSurface->getBasePtr(_dirtyRect->left, _dirtyRect->top), _renderSurface->pitch, _dirtyRect->left, _dirtyRect->top, _dirtyRect->width(), _dirtyRect->height()); - - // Revert the colorMod-state. - _colorMod = oldColorMod; -} - -// Replacement for SDL2's SDL_RenderCopy -void BaseRenderOSystem::drawFromSurface(RenderTicket *ticket, Common::Rect *clipRect) { - TransparentSurface src(*ticket->getSurface(), false); - bool doDelete = false; - if (!clipRect) { - doDelete = true; - clipRect = new Common::Rect(); - clipRect->setWidth(ticket->getSurface()->w); - clipRect->setHeight(ticket->getSurface()->h); - } - - src._enableAlphaBlit = ticket->_hasAlpha; - src.blit(*_renderSurface, ticket->_dstRect.left, ticket->_dstRect.top, ticket->_mirror, clipRect, _colorMod, clipRect->width(), clipRect->height()); - if (doDelete) { - delete clipRect; - } -} -void BaseRenderOSystem::drawFromSurface(const Graphics::Surface *surf, Common::Rect *srcRect, Common::Rect *dstRect, Common::Rect *clipRect, uint32 mirror) { - TransparentSurface src(*surf, false); - bool doDelete = false; - if (!clipRect) { - doDelete = true; - clipRect = new Common::Rect(); - clipRect->setWidth(surf->w); - clipRect->setHeight(surf->h); - } - - src.blit(*_renderSurface, dstRect->left, dstRect->top, mirror, clipRect, _colorMod, clipRect->width(), clipRect->height()); - if (doDelete) { - delete clipRect; - } -} - -////////////////////////////////////////////////////////////////////////// -bool BaseRenderOSystem::drawLine(int x1, int y1, int x2, int y2, uint32 color) { - - if (!_disableDirtyRects) { - warning("BaseRenderOSystem::DrawLine - doesn't work for dirty rects yet"); - } - - byte r = RGBCOLGetR(color); - byte g = RGBCOLGetG(color); - byte b = RGBCOLGetB(color); - byte a = RGBCOLGetA(color); - - //SDL_SetRenderDrawColor(_renderer, r, g, b, a); - //SDL_SetRenderDrawBlendMode(_renderer, SDL_BLENDMODE_BLEND); - - Point32 point1, point2; - point1.x = x1; - point1.y = y1; - pointToScreen(&point1); - - point2.x = x2; - point2.y = y2; - pointToScreen(&point2); - - // TODO: This thing is mostly here until I'm sure about the final color-format. - uint32 colorVal = _renderSurface->format.ARGBToColor(a, r, g, b); - _renderSurface->drawLine(point1.x, point1.y, point2.x, point2.y, colorVal); - //SDL_RenderDrawLine(_renderer, point1.x, point1.y, point2.x, point2.y); - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -BaseImage *BaseRenderOSystem::takeScreenshot() { -// TODO: Clip by viewport. - BaseImage *screenshot = new BaseImage(); - screenshot->copyFrom(_renderSurface); - return screenshot; -} - -////////////////////////////////////////////////////////////////////////// -Common::String BaseRenderOSystem::getName() const { - return "ScummVM-OSystem-renderer"; -} - -////////////////////////////////////////////////////////////////////////// -bool BaseRenderOSystem::setViewport(int left, int top, int right, int bottom) { - Common::Rect rect; - // TODO: Hopefully this is the same logic that ScummVM uses. - rect.left = (int16)(left + _borderLeft); - rect.top = (int16)(top + _borderTop); - rect.right = (int16)((right - left) * _ratioX); - rect.bottom = (int16)((bottom - top) * _ratioY); - - _renderRect = rect; - return STATUS_OK; -} - -Rect32 BaseRenderOSystem::getViewPort() { - Rect32 ret; - ret.top = _renderRect.top; - ret.bottom = _renderRect.bottom; - ret.left = _renderRect.left; - ret.right = _renderRect.right; - return ret; -} - -////////////////////////////////////////////////////////////////////////// -void BaseRenderOSystem::modTargetRect(Common::Rect *rect) { - rect->left = (int16)MathUtil::round(rect->left * _ratioX + _borderLeft - _renderRect.left); - rect->top = (int16)MathUtil::round(rect->top * _ratioY + _borderTop - _renderRect.top); - rect->setWidth((int16)MathUtil::roundUp(rect->width() * _ratioX)); - rect->setHeight((int16)MathUtil::roundUp(rect->height() * _ratioY)); -} - -////////////////////////////////////////////////////////////////////////// -void BaseRenderOSystem::pointFromScreen(Point32 *point) { - point->x = (int16)(point->x / _ratioX - _borderLeft / _ratioX + _renderRect.left); - point->y = (int16)(point->y / _ratioY - _borderTop / _ratioY + _renderRect.top); -} - - -////////////////////////////////////////////////////////////////////////// -void BaseRenderOSystem::pointToScreen(Point32 *point) { - point->x = (int16)MathUtil::roundUp(point->x * _ratioX) + _borderLeft - _renderRect.left; - point->y = (int16)MathUtil::roundUp(point->y * _ratioY) + _borderTop - _renderRect.top; -} - -////////////////////////////////////////////////////////////////////////// -void BaseRenderOSystem::dumpData(const char *filename) { - warning("BaseRenderOSystem::DumpData(%s) - stubbed", filename); // TODO -} - -BaseSurface *BaseRenderOSystem::createSurface() { - return new BaseSurfaceOSystem(_gameRef); -} - -} // end of namespace Wintermute +/* 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. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#include "engines/wintermute/base/gfx/osystem/base_render_osystem.h" +#include "engines/wintermute/base/gfx/osystem/base_surface_osystem.h" +#include "engines/wintermute/base/base_surface_storage.h" +#include "engines/wintermute/base/gfx/base_image.h" +#include "engines/wintermute/math/math_util.h" +#include "engines/wintermute/base/base_game.h" +#include "engines/wintermute/base/base_sprite.h" +#include "common/system.h" +#include "engines/wintermute/graphics/transparent_surface.h" +#include "common/queue.h" +#include "common/config-manager.h" + +namespace Wintermute { + +RenderTicket::RenderTicket(BaseSurfaceOSystem *owner, const Graphics::Surface *surf, Common::Rect *srcRect, Common::Rect *dstRect, bool mirrorX, bool mirrorY, bool disableAlpha) : _owner(owner), + _srcRect(*srcRect), _dstRect(*dstRect), _drawNum(0), _isValid(true), _wantsDraw(true), _hasAlpha(!disableAlpha) { + _colorMod = 0; + _mirror = TransparentSurface::FLIP_NONE; + if (mirrorX) { + _mirror |= TransparentSurface::FLIP_V; + } + if (mirrorY) { + _mirror |= TransparentSurface::FLIP_H; + } + if (surf) { + _surface = new Graphics::Surface(); + _surface->create((uint16)srcRect->width(), (uint16)srcRect->height(), surf->format); + assert(_surface->format.bytesPerPixel == 4); + // Get a clipped copy of the surface + for (int i = 0; i < _surface->h; i++) { + memcpy(_surface->getBasePtr(0, i), surf->getBasePtr(srcRect->left, srcRect->top + i), srcRect->width() * _surface->format.bytesPerPixel); + } + // Then scale it if necessary + if (dstRect->width() != srcRect->width() || dstRect->height() != srcRect->height()) { + TransparentSurface src(*_surface, false); + Graphics::Surface *temp = src.scale(dstRect->width(), dstRect->height()); + _surface->free(); + delete _surface; + _surface = temp; + } + } else { + _surface = NULL; + } +} + +RenderTicket::~RenderTicket() { + if (_surface) { + _surface->free(); + delete _surface; + } +} + +bool RenderTicket::operator==(RenderTicket &t) { + if ((t._srcRect != _srcRect) || + (t._dstRect != _dstRect) || + (t._mirror != _mirror) || + (t._owner != _owner) || + (t._hasAlpha != _hasAlpha) || + (t._colorMod != _colorMod)) { + return false; + } + return true; +} + +BaseRenderer *makeOSystemRenderer(BaseGame *inGame) { + return new BaseRenderOSystem(inGame); +} + +////////////////////////////////////////////////////////////////////////// +BaseRenderOSystem::BaseRenderOSystem(BaseGame *inGame) : BaseRenderer(inGame) { + _renderSurface = new Graphics::Surface(); + _blankSurface = new Graphics::Surface(); + _drawNum = 1; + _needsFlip = true; + + _borderLeft = _borderRight = _borderTop = _borderBottom = 0; + _ratioX = _ratioY = 1.0f; + setAlphaMod(255); + setColorMod(255, 255, 255); + _dirtyRect = NULL; +} + +////////////////////////////////////////////////////////////////////////// +BaseRenderOSystem::~BaseRenderOSystem() { + _renderSurface->free(); + delete _renderSurface; + _blankSurface->free(); + delete _blankSurface; + TransparentSurface::destroyLookup(); +} + +////////////////////////////////////////////////////////////////////////// +bool BaseRenderOSystem::initRenderer(int width, int height, bool windowed) { + _width = width; + _height = height; + _renderRect.setWidth(_width); + _renderRect.setHeight(_height); + + _realWidth = width; + _realHeight = height; + + //TODO: Tiny resolution-displays might want to do some resolution-selection logic here + + //_realWidth = BaseEngine::instance().getRegistry()->readInt("Debug", "ForceResWidth", _width); + //_realHeight = BaseEngine::instance().getRegistry()->readInt("Debug", "ForceResHeight", _height); + + float origAspect = (float)_width / (float)_height; + float realAspect = (float)_realWidth / (float)_realHeight; + + float ratio; + if (origAspect < realAspect) { + // normal to wide + ratio = (float)_realHeight / (float)_height; + } else { + // wide to normal + ratio = (float)_realWidth / (float)_width; + } + + _borderLeft = (int)((_realWidth - (_width * ratio)) / 2); + _borderRight = (int)(_realWidth - (_width * ratio) - _borderLeft); + + _borderTop = (int)((_realHeight - (_height * ratio)) / 2); + _borderBottom = (int)(_realHeight - (_height * ratio) - _borderTop); + + + + _ratioX = (float)(_realWidth - _borderLeft - _borderRight) / (float)_width; + _ratioY = (float)(_realHeight - _borderTop - _borderBottom) / (float)_height; + + _windowed = !ConfMan.getBool("fullscreen"); + + Graphics::PixelFormat format(4, 8, 8, 8, 8, 16, 8, 0, 24); + g_system->beginGFXTransaction(); + g_system->initSize(_width, _height, &format); + OSystem::TransactionError gfxError = g_system->endGFXTransaction(); + + if (gfxError != OSystem::kTransactionSuccess) { + warning("Couldn't setup GFX-backend for %dx%dx%d", _width, _height, format.bytesPerPixel * 8); + return STATUS_FAILED; + } + + g_system->showMouse(false); + + _renderSurface->create(g_system->getWidth(), g_system->getHeight(), g_system->getScreenFormat()); + _blankSurface->create(g_system->getWidth(), g_system->getHeight(), g_system->getScreenFormat()); + _blankSurface->fillRect(Common::Rect(0, 0, _blankSurface->h, _blankSurface->w), _blankSurface->format.ARGBToColor(255, 0, 0, 0)); + _active = true; + + _clearColor = _renderSurface->format.ARGBToColor(255, 0, 0, 0); + + return STATUS_OK; +} + +void BaseRenderOSystem::setAlphaMod(byte alpha) { + byte r = RGBCOLGetR(_colorMod); + byte g = RGBCOLGetB(_colorMod); + byte b = RGBCOLGetB(_colorMod); + _colorMod = BS_ARGB(alpha, r, g, b); +} + +void BaseRenderOSystem::setColorMod(byte r, byte g, byte b) { + byte alpha = RGBCOLGetA(_colorMod); + _colorMod = BS_ARGB(alpha, r, g, b); +} + +bool BaseRenderOSystem::indicatorFlip() { + g_system->copyRectToScreen((byte *)_renderSurface->getBasePtr(_indicatorX, _indicatorY), _renderSurface->pitch, _indicatorX, _indicatorY, _indicatorWidthDrawn, _indicatorHeight); + g_system->updateScreen(); + return STATUS_OK; +} + +bool BaseRenderOSystem::flip() { + if (!_disableDirtyRects) { + drawTickets(); + } else { + // Clear the scale-buffered tickets that wasn't reused. + RenderQueueIterator it = _renderQueue.begin(); + while (it != _renderQueue.end()) { + if ((*it)->_wantsDraw == false) { + RenderTicket *ticket = *it; + it = _renderQueue.erase(it); + delete ticket; + } else { + (*it)->_wantsDraw = false; + ++it; + } + } + } + if (_needsFlip || _disableDirtyRects) { + if (_disableDirtyRects) { + g_system->copyRectToScreen((byte *)_renderSurface->pixels, _renderSurface->pitch, 0, 0, _renderSurface->w, _renderSurface->h); + } + // g_system->copyRectToScreen((byte *)_renderSurface->pixels, _renderSurface->pitch, _dirtyRect->left, _dirtyRect->top, _dirtyRect->width(), _dirtyRect->height()); + delete _dirtyRect; + _dirtyRect = NULL; + g_system->updateScreen(); + _needsFlip = false; + } + _drawNum = 1; + + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +bool BaseRenderOSystem::fill(byte r, byte g, byte b, Common::Rect *rect) { + _clearColor = _renderSurface->format.ARGBToColor(0xFF, r, g, b); + if (!_disableDirtyRects) { + return STATUS_OK; + } + if (!rect) { +// TODO: This should speed things up, but for some reason it misses the size by quite a bit. +/* if (r == 0 && g == 0 && b == 0) { + // Simply memcpy from the buffered black-surface, way faster than Surface::fillRect. + memcpy(_renderSurface->pixels, _blankSurface->pixels, _renderSurface->pitch * _renderSurface->h); + return STATUS_OK; + }*/ + rect = &_renderRect; + } + // TODO: This doesn't work with dirty rects + _renderSurface->fillRect(*rect, _clearColor); + + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +void BaseRenderOSystem::fade(uint16 alpha) { + byte dwAlpha = (byte)(255 - alpha); + return fadeToColor(0, 0, 0, dwAlpha); +} + + +////////////////////////////////////////////////////////////////////////// +void BaseRenderOSystem::fadeToColor(byte r, byte g, byte b, byte a, Common::Rect *rect) { + // This particular warning is rather messy, as this function is called a ton, + // thus we avoid printing it more than once. + + // TODO: Add fading with dirty rects. + if (!_disableDirtyRects) { + warning("BaseRenderOSystem::FadeToColor - Breaks when using dirty rects"); + } + + Common::Rect fillRect; + + if (rect) { + fillRect.left = rect->left; + fillRect.top = rect->top; + fillRect.setWidth(rect->width()); + fillRect.setHeight(rect->height()); + } else { + Rect32 rc; + _gameRef->getCurrentViewportRect(&rc); + fillRect.left = (int16)rc.left; + fillRect.top = (int16)rc.top; + fillRect.setWidth((int16)(rc.right - rc.left)); + fillRect.setHeight((int16)(rc.bottom - rc.top)); + } + modTargetRect(&fillRect); + + //TODO: This is only here until I'm sure about the final pixelformat + uint32 col = _renderSurface->format.ARGBToColor(a, r, g, b); + + setAlphaMod(255); + setColorMod(255, 255, 255); + Graphics::Surface surf; + surf.create((uint16)fillRect.width(), (uint16)fillRect.height(), _renderSurface->format); + Common::Rect sizeRect(fillRect); + sizeRect.translate(-fillRect.top, -fillRect.left); + surf.fillRect(fillRect, col); + drawSurface(NULL, &surf, &sizeRect, &fillRect, false, false); + surf.free(); + + //SDL_SetRenderDrawColor(_renderer, r, g, b, a); + //SDL_SetRenderDrawBlendMode(_renderer, SDL_BLENDMODE_BLEND); + //SDL_RenderFillRect(_renderer, &fillRect); +} + +Graphics::PixelFormat BaseRenderOSystem::getPixelFormat() const { + return _renderSurface->format; +} + +void BaseRenderOSystem::drawSurface(BaseSurfaceOSystem *owner, const Graphics::Surface *surf, Common::Rect *srcRect, Common::Rect *dstRect, bool mirrorX, bool mirrorY, bool disableAlpha) { + // Skip rects that are completely outside the screen: + if ((dstRect->left < 0 && dstRect->right < 0) || (dstRect->top < 0 && dstRect->bottom < 0)) { + return; + } + + if (owner) { // Fade-tickets are owner-less + RenderTicket compare(owner, NULL, srcRect, dstRect, mirrorX, mirrorY, disableAlpha); + compare._colorMod = _colorMod; + RenderQueueIterator it; + for (it = _renderQueue.begin(); it != _renderQueue.end(); ++it) { + if ((*it)->_owner == owner && *(*it) == compare && (*it)->_isValid) { + (*it)->_colorMod = _colorMod; + if (_disableDirtyRects) { + drawFromSurface(*it, NULL); + } else { + drawFromTicket(*it); + } + return; + } + } + } + RenderTicket *ticket = new RenderTicket(owner, surf, srcRect, dstRect, mirrorX, mirrorY, disableAlpha); + ticket->_colorMod = _colorMod; + if (!_disableDirtyRects) { + drawFromTicket(ticket); + } else { + ticket->_wantsDraw = true; + _renderQueue.push_back(ticket); + drawFromSurface(ticket, NULL); + } +} + +void BaseRenderOSystem::invalidateTicket(RenderTicket *renderTicket) { + addDirtyRect(renderTicket->_dstRect); + renderTicket->_isValid = false; +// renderTicket->_canDelete = true; // TODO: Maybe readd this, to avoid even more duplicates. +} + +void BaseRenderOSystem::invalidateTicketsFromSurface(BaseSurfaceOSystem *surf) { + RenderQueueIterator it; + for (it = _renderQueue.begin(); it != _renderQueue.end(); ++it) { + if ((*it)->_owner == surf) { + invalidateTicket(*it); + } + } +} + +void BaseRenderOSystem::drawFromTicket(RenderTicket *renderTicket) { + renderTicket->_wantsDraw = true; + // A new item always has _drawNum == 0 + if (renderTicket->_drawNum == 0) { + // In-order + if (_renderQueue.empty() || _drawNum > (_renderQueue.back())->_drawNum) { + renderTicket->_drawNum = _drawNum++; + _renderQueue.push_back(renderTicket); + addDirtyRect(renderTicket->_dstRect); + } else { + // Before something + Common::List::iterator pos; + for (pos = _renderQueue.begin(); pos != _renderQueue.end(); pos++) { + if ((*pos)->_drawNum >= _drawNum) { + break; + } + } + _renderQueue.insert(pos, renderTicket); + Common::List::iterator it; + renderTicket->_drawNum = _drawNum++; + // Increment the following tickets, so they still are in line + for (it = pos; it != _renderQueue.end(); ++it) { + (*it)->_drawNum++; + (*it)->_wantsDraw = false; + } + addDirtyRect(renderTicket->_dstRect); + } + } else { + // Was drawn last round, still in the same order + if (_drawNum == renderTicket->_drawNum) { + _drawNum++; + } else { + // Remove the ticket from the list + RenderQueueIterator it = _renderQueue.begin(); + while (it != _renderQueue.end()) { + if ((*it) == renderTicket) { + it = _renderQueue.erase(it); + break; + } else { + ++it; + } + } + if (it != _renderQueue.end()) { + // Decreement the following tickets. + for (; it != _renderQueue.end(); ++it) { + (*it)->_drawNum--; + } + } + // Is not in order, so readd it as if it was a new ticket + renderTicket->_drawNum = 0; + drawFromTicket(renderTicket); + } + } +} + +void BaseRenderOSystem::addDirtyRect(const Common::Rect &rect) { + if (!_dirtyRect) { + _dirtyRect = new Common::Rect(rect); + } else { + _dirtyRect->extend(rect); + } + _dirtyRect->clip(_renderRect); +} + +void BaseRenderOSystem::drawTickets() { + RenderQueueIterator it = _renderQueue.begin(); + // Clean out the old tickets + int decrement = 0; + while (it != _renderQueue.end()) { + if ((*it)->_wantsDraw == false || (*it)->_isValid == false) { + RenderTicket *ticket = *it; + addDirtyRect((*it)->_dstRect); + it = _renderQueue.erase(it); + delete ticket; + decrement++; + } else { + (*it)->_drawNum -= decrement; + ++it; + } + } + if (!_dirtyRect || _dirtyRect->width() == 0 || _dirtyRect->height() == 0) { + return; + } + // The color-mods are stored in the RenderTickets on add, since we set that state again during + // draw, we need to keep track of what it was prior to draw. + uint32 oldColorMod = _colorMod; + + // Apply the clear-color to the dirty rect. + _renderSurface->fillRect(*_dirtyRect, _clearColor); + _drawNum = 1; + for (it = _renderQueue.begin(); it != _renderQueue.end(); ++it) { + RenderTicket *ticket = *it; + assert(ticket->_drawNum == _drawNum++); + if (ticket->_isValid && ticket->_dstRect.intersects(*_dirtyRect)) { + // dstClip is the area we want redrawn. + Common::Rect dstClip(ticket->_dstRect); + // reduce it to the dirty rect + dstClip.clip(*_dirtyRect); + // we need to keep track of the position to redraw the dirty rect + Common::Rect pos(dstClip); + int16 offsetX = ticket->_dstRect.left; + int16 offsetY = ticket->_dstRect.top; + // convert from screen-coords to surface-coords. + dstClip.translate(-offsetX, -offsetY); + + _colorMod = ticket->_colorMod; + drawFromSurface(ticket->getSurface(), &ticket->_srcRect, &pos, &dstClip, ticket->_mirror); + _needsFlip = true; + } + // Some tickets want redraw but don't actually clip the dirty area (typically the ones that shouldnt become clear-color) + ticket->_wantsDraw = false; + } + g_system->copyRectToScreen((byte *)_renderSurface->getBasePtr(_dirtyRect->left, _dirtyRect->top), _renderSurface->pitch, _dirtyRect->left, _dirtyRect->top, _dirtyRect->width(), _dirtyRect->height()); + + // Revert the colorMod-state. + _colorMod = oldColorMod; +} + +// Replacement for SDL2's SDL_RenderCopy +void BaseRenderOSystem::drawFromSurface(RenderTicket *ticket, Common::Rect *clipRect) { + TransparentSurface src(*ticket->getSurface(), false); + bool doDelete = false; + if (!clipRect) { + doDelete = true; + clipRect = new Common::Rect(); + clipRect->setWidth(ticket->getSurface()->w); + clipRect->setHeight(ticket->getSurface()->h); + } + + src._enableAlphaBlit = ticket->_hasAlpha; + src.blit(*_renderSurface, ticket->_dstRect.left, ticket->_dstRect.top, ticket->_mirror, clipRect, _colorMod, clipRect->width(), clipRect->height()); + if (doDelete) { + delete clipRect; + } +} +void BaseRenderOSystem::drawFromSurface(const Graphics::Surface *surf, Common::Rect *srcRect, Common::Rect *dstRect, Common::Rect *clipRect, uint32 mirror) { + TransparentSurface src(*surf, false); + bool doDelete = false; + if (!clipRect) { + doDelete = true; + clipRect = new Common::Rect(); + clipRect->setWidth(surf->w); + clipRect->setHeight(surf->h); + } + + src.blit(*_renderSurface, dstRect->left, dstRect->top, mirror, clipRect, _colorMod, clipRect->width(), clipRect->height()); + if (doDelete) { + delete clipRect; + } +} + +////////////////////////////////////////////////////////////////////////// +bool BaseRenderOSystem::drawLine(int x1, int y1, int x2, int y2, uint32 color) { + + if (!_disableDirtyRects) { + warning("BaseRenderOSystem::DrawLine - doesn't work for dirty rects yet"); + } + + byte r = RGBCOLGetR(color); + byte g = RGBCOLGetG(color); + byte b = RGBCOLGetB(color); + byte a = RGBCOLGetA(color); + + //SDL_SetRenderDrawColor(_renderer, r, g, b, a); + //SDL_SetRenderDrawBlendMode(_renderer, SDL_BLENDMODE_BLEND); + + Point32 point1, point2; + point1.x = x1; + point1.y = y1; + pointToScreen(&point1); + + point2.x = x2; + point2.y = y2; + pointToScreen(&point2); + + // TODO: This thing is mostly here until I'm sure about the final color-format. + uint32 colorVal = _renderSurface->format.ARGBToColor(a, r, g, b); + _renderSurface->drawLine(point1.x, point1.y, point2.x, point2.y, colorVal); + //SDL_RenderDrawLine(_renderer, point1.x, point1.y, point2.x, point2.y); + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +BaseImage *BaseRenderOSystem::takeScreenshot() { +// TODO: Clip by viewport. + BaseImage *screenshot = new BaseImage(); + screenshot->copyFrom(_renderSurface); + return screenshot; +} + +////////////////////////////////////////////////////////////////////////// +Common::String BaseRenderOSystem::getName() const { + return "ScummVM-OSystem-renderer"; +} + +////////////////////////////////////////////////////////////////////////// +bool BaseRenderOSystem::setViewport(int left, int top, int right, int bottom) { + Common::Rect rect; + // TODO: Hopefully this is the same logic that ScummVM uses. + rect.left = (int16)(left + _borderLeft); + rect.top = (int16)(top + _borderTop); + rect.right = (int16)((right - left) * _ratioX); + rect.bottom = (int16)((bottom - top) * _ratioY); + + _renderRect = rect; + return STATUS_OK; +} + +Rect32 BaseRenderOSystem::getViewPort() { + Rect32 ret; + ret.top = _renderRect.top; + ret.bottom = _renderRect.bottom; + ret.left = _renderRect.left; + ret.right = _renderRect.right; + return ret; +} + +////////////////////////////////////////////////////////////////////////// +void BaseRenderOSystem::modTargetRect(Common::Rect *rect) { + rect->left = (int16)MathUtil::round(rect->left * _ratioX + _borderLeft - _renderRect.left); + rect->top = (int16)MathUtil::round(rect->top * _ratioY + _borderTop - _renderRect.top); + rect->setWidth((int16)MathUtil::roundUp(rect->width() * _ratioX)); + rect->setHeight((int16)MathUtil::roundUp(rect->height() * _ratioY)); +} + +////////////////////////////////////////////////////////////////////////// +void BaseRenderOSystem::pointFromScreen(Point32 *point) { + point->x = (int16)(point->x / _ratioX - _borderLeft / _ratioX + _renderRect.left); + point->y = (int16)(point->y / _ratioY - _borderTop / _ratioY + _renderRect.top); +} + + +////////////////////////////////////////////////////////////////////////// +void BaseRenderOSystem::pointToScreen(Point32 *point) { + point->x = (int16)MathUtil::roundUp(point->x * _ratioX) + _borderLeft - _renderRect.left; + point->y = (int16)MathUtil::roundUp(point->y * _ratioY) + _borderTop - _renderRect.top; +} + +////////////////////////////////////////////////////////////////////////// +void BaseRenderOSystem::dumpData(const char *filename) { + warning("BaseRenderOSystem::DumpData(%s) - stubbed", filename); // TODO +} + +BaseSurface *BaseRenderOSystem::createSurface() { + return new BaseSurfaceOSystem(_gameRef); +} + +} // end of namespace Wintermute diff --git a/engines/wintermute/base/gfx/osystem/base_render_osystem.h b/engines/wintermute/base/gfx/osystem/base_render_osystem.h index aebb4cf888..1e72508cd0 100644 --- a/engines/wintermute/base/gfx/osystem/base_render_osystem.h +++ b/engines/wintermute/base/gfx/osystem/base_render_osystem.h @@ -1,131 +1,131 @@ -/* 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. - * - */ - -/* - * This file is based on WME Lite. - * http://dead-code.org/redir.php?target=wmelite - * Copyright (c) 2011 Jan Nedoma - */ - -#ifndef WINTERMUTE_BASE_RENDERER_SDL_H -#define WINTERMUTE_BASE_RENDERER_SDL_H - -#include "engines/wintermute/base/gfx/base_renderer.h" -#include "common/rect.h" -#include "graphics/surface.h" -#include "common/list.h" - -namespace Wintermute { -class BaseSurfaceOSystem; -class RenderTicket { - Graphics::Surface *_surface; -public: - RenderTicket(BaseSurfaceOSystem *owner, const Graphics::Surface *surf, Common::Rect *srcRect, Common::Rect *dstRest, bool mirrorX = false, bool mirrorY = false, bool disableAlpha = false); - RenderTicket() : _isValid(true), _wantsDraw(false), _drawNum(0) {} - ~RenderTicket(); - const Graphics::Surface *getSurface() { return _surface; } - Common::Rect _srcRect; - Common::Rect _dstRect; - uint32 _mirror; - bool _hasAlpha; - - bool _isValid; - bool _wantsDraw; - uint32 _drawNum; - uint32 _colorMod; - - BaseSurfaceOSystem *_owner; - bool operator==(RenderTicket &a); -}; - -class BaseRenderOSystem : public BaseRenderer { -public: - BaseRenderOSystem(BaseGame *inGame); - ~BaseRenderOSystem(); - - Common::String getName() const; - - bool initRenderer(int width, int height, bool windowed); - bool flip(); - virtual bool indicatorFlip(); - bool fill(byte r, byte g, byte b, Common::Rect *rect = NULL); - Graphics::PixelFormat getPixelFormat() const; - void fade(uint16 alpha); - void fadeToColor(byte r, byte g, byte b, byte a, Common::Rect *rect = NULL); - - bool drawLine(int x1, int y1, int x2, int y2, uint32 color); - - BaseImage *takeScreenshot(); - - void setAlphaMod(byte alpha); - void setColorMod(byte r, byte g, byte b); - void invalidateTicket(RenderTicket *renderTicket); - void invalidateTicketsFromSurface(BaseSurfaceOSystem *surf); - void drawFromTicket(RenderTicket *renderTicket); - - bool setViewport(int left, int top, int right, int bottom); - bool setViewport(Rect32 *rect) { return BaseRenderer::setViewport(rect); } - Rect32 getViewPort(); - void modTargetRect(Common::Rect *rect); - void pointFromScreen(Point32 *point); - void pointToScreen(Point32 *point); - - void dumpData(const char *filename); - - float getScaleRatioX() const { - return _ratioX; - } - float getScaleRatioY() const { - return _ratioY; - } - - void drawSurface(BaseSurfaceOSystem *owner, const Graphics::Surface *surf, Common::Rect *srcRect, Common::Rect *dstRect, bool mirrorX, bool mirrorY, bool disableAlpha = false); - BaseSurface *createSurface(); -private: - void addDirtyRect(const Common::Rect &rect); - void drawTickets(); - void drawFromSurface(RenderTicket *ticket, Common::Rect *clipRect); - void drawFromSurface(const Graphics::Surface *surf, Common::Rect *srcRect, Common::Rect *dstRect, Common::Rect *clipRect, uint32 mirror); - typedef Common::List::iterator RenderQueueIterator; - Common::Rect *_dirtyRect; - Common::List _renderQueue; - bool _needsFlip; - uint32 _drawNum; - Common::Rect _renderRect; - Graphics::Surface *_renderSurface; - Graphics::Surface *_blankSurface; - - int _borderLeft; - int _borderTop; - int _borderRight; - int _borderBottom; - - static const bool _disableDirtyRects = true; - float _ratioX; - float _ratioY; - uint32 _colorMod; - uint32 _clearColor; -}; - -} // end of namespace Wintermute - -#endif +/* 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. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_BASE_RENDERER_SDL_H +#define WINTERMUTE_BASE_RENDERER_SDL_H + +#include "engines/wintermute/base/gfx/base_renderer.h" +#include "common/rect.h" +#include "graphics/surface.h" +#include "common/list.h" + +namespace Wintermute { +class BaseSurfaceOSystem; +class RenderTicket { + Graphics::Surface *_surface; +public: + RenderTicket(BaseSurfaceOSystem *owner, const Graphics::Surface *surf, Common::Rect *srcRect, Common::Rect *dstRest, bool mirrorX = false, bool mirrorY = false, bool disableAlpha = false); + RenderTicket() : _isValid(true), _wantsDraw(false), _drawNum(0) {} + ~RenderTicket(); + const Graphics::Surface *getSurface() { return _surface; } + Common::Rect _srcRect; + Common::Rect _dstRect; + uint32 _mirror; + bool _hasAlpha; + + bool _isValid; + bool _wantsDraw; + uint32 _drawNum; + uint32 _colorMod; + + BaseSurfaceOSystem *_owner; + bool operator==(RenderTicket &a); +}; + +class BaseRenderOSystem : public BaseRenderer { +public: + BaseRenderOSystem(BaseGame *inGame); + ~BaseRenderOSystem(); + + Common::String getName() const; + + bool initRenderer(int width, int height, bool windowed); + bool flip(); + virtual bool indicatorFlip(); + bool fill(byte r, byte g, byte b, Common::Rect *rect = NULL); + Graphics::PixelFormat getPixelFormat() const; + void fade(uint16 alpha); + void fadeToColor(byte r, byte g, byte b, byte a, Common::Rect *rect = NULL); + + bool drawLine(int x1, int y1, int x2, int y2, uint32 color); + + BaseImage *takeScreenshot(); + + void setAlphaMod(byte alpha); + void setColorMod(byte r, byte g, byte b); + void invalidateTicket(RenderTicket *renderTicket); + void invalidateTicketsFromSurface(BaseSurfaceOSystem *surf); + void drawFromTicket(RenderTicket *renderTicket); + + bool setViewport(int left, int top, int right, int bottom); + bool setViewport(Rect32 *rect) { return BaseRenderer::setViewport(rect); } + Rect32 getViewPort(); + void modTargetRect(Common::Rect *rect); + void pointFromScreen(Point32 *point); + void pointToScreen(Point32 *point); + + void dumpData(const char *filename); + + float getScaleRatioX() const { + return _ratioX; + } + float getScaleRatioY() const { + return _ratioY; + } + + void drawSurface(BaseSurfaceOSystem *owner, const Graphics::Surface *surf, Common::Rect *srcRect, Common::Rect *dstRect, bool mirrorX, bool mirrorY, bool disableAlpha = false); + BaseSurface *createSurface(); +private: + void addDirtyRect(const Common::Rect &rect); + void drawTickets(); + void drawFromSurface(RenderTicket *ticket, Common::Rect *clipRect); + void drawFromSurface(const Graphics::Surface *surf, Common::Rect *srcRect, Common::Rect *dstRect, Common::Rect *clipRect, uint32 mirror); + typedef Common::List::iterator RenderQueueIterator; + Common::Rect *_dirtyRect; + Common::List _renderQueue; + bool _needsFlip; + uint32 _drawNum; + Common::Rect _renderRect; + Graphics::Surface *_renderSurface; + Graphics::Surface *_blankSurface; + + int _borderLeft; + int _borderTop; + int _borderRight; + int _borderBottom; + + static const bool _disableDirtyRects = true; + float _ratioX; + float _ratioY; + uint32 _colorMod; + uint32 _clearColor; +}; + +} // end of namespace Wintermute + +#endif diff --git a/engines/wintermute/base/gfx/osystem/base_surface_osystem.cpp b/engines/wintermute/base/gfx/osystem/base_surface_osystem.cpp index 7724a93481..d5464782a3 100644 --- a/engines/wintermute/base/gfx/osystem/base_surface_osystem.cpp +++ b/engines/wintermute/base/gfx/osystem/base_surface_osystem.cpp @@ -1,429 +1,429 @@ -/* 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. - * - */ - -/* - * This file is based on WME Lite. - * http://dead-code.org/redir.php?target=wmelite - * Copyright (c) 2011 Jan Nedoma - */ - -#include "engines/wintermute/base/file/base_file.h" -#include "engines/wintermute/base/base_file_manager.h" -#include "engines/wintermute/base/base_game.h" -#include "engines/wintermute/base/gfx/osystem/base_surface_osystem.h" -#include "engines/wintermute/base/gfx/osystem/base_render_osystem.h" -#include "engines/wintermute/base/gfx/base_image.h" -#include "engines/wintermute/platform_osystem.h" -#include "graphics/decoders/png.h" -#include "graphics/decoders/bmp.h" -#include "graphics/decoders/jpeg.h" -#include "graphics/decoders/tga.h" -#include "engines/wintermute/graphics/transparent_surface.h" -#include "graphics/pixelformat.h" -#include "graphics/surface.h" -#include "common/stream.h" -#include "common/system.h" - -namespace Wintermute { - -////////////////////////////////////////////////////////////////////////// -BaseSurfaceOSystem::BaseSurfaceOSystem(BaseGame *inGame) : BaseSurface(inGame) { - _surface = new Graphics::Surface(); - _alphaMask = NULL; - _hasAlpha = true; - _lockPixels = NULL; - _lockPitch = 0; - _loaded = false; -} - -////////////////////////////////////////////////////////////////////////// -BaseSurfaceOSystem::~BaseSurfaceOSystem() { - if (_surface) { - _surface->free(); - delete _surface; - _surface = NULL; - } - - delete[] _alphaMask; - _alphaMask = NULL; - - _gameRef->addMem(-_width * _height * 4); - BaseRenderOSystem *renderer = static_cast(_gameRef->_renderer); - renderer->invalidateTicketsFromSurface(this); -} - -bool hasTransparency(Graphics::Surface *surf) { - if (surf->format.bytesPerPixel != 4) { - warning("hasTransparency:: non 32 bpp surface passed as argument"); - return false; - } - uint8 r, g, b, a; - for (int i = 0; i < surf->h; i++) { - for (int j = 0; j < surf->w; j++) { - uint32 pix = *(uint32 *)surf->getBasePtr(j, i); - surf->format.colorToARGB(pix, a, r, g, b); - if (a != 255) { - return true; - } - } - } - return false; -} - -////////////////////////////////////////////////////////////////////////// -bool BaseSurfaceOSystem::create(const Common::String &filename, bool defaultCK, byte ckRed, byte ckGreen, byte ckBlue, int lifeTime, bool keepLoaded) { - /* BaseRenderOSystem *renderer = static_cast(_gameRef->_renderer); */ - _filename = filename; -// const Graphics::Surface *surface = image->getSurface(); - - if (defaultCK) { - ckRed = 255; - ckGreen = 0; - ckBlue = 255; - } - - _ckDefault = defaultCK; - _ckRed = ckRed; - _ckGreen = ckGreen; - _ckBlue = ckBlue; - - if (_lifeTime == 0 || lifeTime == -1 || lifeTime > _lifeTime) { - _lifeTime = lifeTime; - } - - _keepLoaded = keepLoaded; - if (_keepLoaded) { - _lifeTime = -1; - } - - return STATUS_OK; -} - -bool BaseSurfaceOSystem::finishLoad() { - BaseImage *image = new BaseImage(); - if (!image->loadFile(_filename)) { - return false; - } - - _width = image->getSurface()->w; - _height = image->getSurface()->h; - - bool isSaveGameGrayscale = scumm_strnicmp(_filename.c_str(), "savegame:", 9) == 0 && (_filename.c_str()[_filename.size() - 1] == 'g' || _filename.c_str()[_filename.size() - 1] == 'G'); - if (isSaveGameGrayscale) { - warning("grayscaleConversion not yet implemented"); - // FIBITMAP *newImg = FreeImage_ConvertToGreyscale(img); TODO - } - - // no alpha, set color key - /* if (surface->format.bytesPerPixel != 4) - SDL_SetColorKey(surf, SDL_TRUE, SDL_MapRGB(surf->format, ck_red, ck_green, ck_blue));*/ - - // convert 32-bit BMPs to 24-bit or they appear totally transparent (does any app actually write alpha in BMP properly?) - // Well, actually, we don't convert via 24-bit as the color-key application overwrites the Alpha-channel anyhow. - _surface->free(); - delete _surface; - if (_filename.hasSuffix(".bmp") && image->getSurface()->format.bytesPerPixel == 4) { - _surface = image->getSurface()->convertTo(g_system->getScreenFormat(), image->getPalette()); - TransparentSurface trans(*_surface); - trans.applyColorKey(_ckRed, _ckGreen, _ckBlue); - } else if (image->getSurface()->format.bytesPerPixel == 1 && image->getPalette()) { - _surface = image->getSurface()->convertTo(g_system->getScreenFormat(), image->getPalette()); - TransparentSurface trans(*_surface); - trans.applyColorKey(_ckRed, _ckGreen, _ckBlue, true); - } else if (image->getSurface()->format.bytesPerPixel >= 3 && image->getSurface()->format != g_system->getScreenFormat()) { - _surface = image->getSurface()->convertTo(g_system->getScreenFormat()); - if (image->getSurface()->format.bytesPerPixel == 3) { - TransparentSurface trans(*_surface); - trans.applyColorKey(_ckRed, _ckGreen, _ckBlue, true); - } - } else { - _surface = new Graphics::Surface(); - _surface->copyFrom(*image->getSurface()); - } - - _hasAlpha = hasTransparency(_surface); - _valid = true; - - _gameRef->addMem(_width * _height * 4); - - delete image; - - _loaded = true; - - return true; -} - -////////////////////////////////////////////////////////////////////////// -void BaseSurfaceOSystem::genAlphaMask(Graphics::Surface *surface) { - warning("BaseSurfaceOSystem::GenAlphaMask - Not ported yet"); - return; - // TODO: Reimplement this - delete[] _alphaMask; - _alphaMask = NULL; - if (!surface) { - return; - } - - bool hasColorKey; - /* uint32 colorKey; */ - uint8 ckRed, ckGreen, ckBlue; - /* if (SDL_GetColorKey(surface, &colorKey) == 0) { - hasColorKey = true; - SDL_GetRGB(colorKey, surface->format, &ckRed, &ckGreen, &ckBlue); - } else hasColorKey = false; - */ - _alphaMask = new byte[surface->w * surface->h]; - - bool hasTransparency = false; - for (int y = 0; y < surface->h; y++) { - for (int x = 0; x < surface->w; x++) { - uint32 pixel = getPixelAt(surface, x, y); - - uint8 r, g, b, a; - surface->format.colorToARGB(pixel, a, r, g, b); - //SDL_GetRGBA(pixel, surface->format, &r, &g, &b, &a); - - if (hasColorKey && r == ckRed && g == ckGreen && b == ckBlue) { - a = 0; - } - - _alphaMask[y * surface->w + x] = a; - if (a < 255) { - hasTransparency = true; - } - } - } - - if (!hasTransparency) { - delete[] _alphaMask; - _alphaMask = NULL; - } -} - -////////////////////////////////////////////////////////////////////////// -uint32 BaseSurfaceOSystem::getPixelAt(Graphics::Surface *surface, int x, int y) { - warning("BaseSurfaceOSystem::GetPixel - Not ported yet"); - int bpp = surface->format.bytesPerPixel; - /* Here p is the address to the pixel we want to retrieve */ - uint8 *p = (uint8 *)surface->pixels + y * surface->pitch + x * bpp; - - switch (bpp) { - case 1: - return *p; - break; - - case 2: - return *(uint16 *)p; - break; - - case 3: -#ifdef SCUMM_BIG_ENDIAN - // if (SDL_BYTEORDER == SDL_BIG_ENDIAN) - return p[0] << 16 | p[1] << 8 | p[2]; -#else - //else - return p[0] | p[1] << 8 | p[2] << 16; -#endif - break; - - case 4: - return *(uint32 *)p; - break; - - default: - return 0; /* shouldn't happen, but avoids warnings */ - } - return 0; -} - -////////////////////////////////////////////////////////////////////////// -bool BaseSurfaceOSystem::create(int width, int height) { - _width = width; - _height = height; - - _gameRef->addMem(_width * _height * 4); - - _valid = true; - - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -bool BaseSurfaceOSystem::isTransparentAt(int x, int y) { - return isTransparentAtLite(x, y); -} - -////////////////////////////////////////////////////////////////////////// -bool BaseSurfaceOSystem::isTransparentAtLite(int x, int y) { - if (x < 0 || x >= _surface->w || y < 0 || y >= _surface->h) { - return true; - } - - if (_surface->format.bytesPerPixel == 4) { - uint32 pixel = *(uint32 *)_surface->getBasePtr(x, y); - uint8 r, g, b, a; - _surface->format.colorToARGB(pixel, a, r, g, b); - if (a <= 128) { - return true; - } else { - return false; - } - } - - return false; -} - -////////////////////////////////////////////////////////////////////////// -bool BaseSurfaceOSystem::startPixelOp() { - //SDL_LockTexture(_texture, NULL, &_lockPixels, &_lockPitch); - // Any pixel-op makes the caching useless: - BaseRenderOSystem *renderer = static_cast(_gameRef->_renderer); - renderer->invalidateTicketsFromSurface(this); - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -bool BaseSurfaceOSystem::endPixelOp() { - //SDL_UnlockTexture(_texture); - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool BaseSurfaceOSystem::display(int x, int y, Rect32 rect, TSpriteBlendMode blendMode, bool mirrorX, bool mirrorY) { - return drawSprite(x, y, &rect, 100, 100, 0xFFFFFFFF, true, blendMode, mirrorX, mirrorY); -} - - -////////////////////////////////////////////////////////////////////////// -bool BaseSurfaceOSystem::displayTrans(int x, int y, Rect32 rect, uint32 alpha, TSpriteBlendMode blendMode, bool mirrorX, bool mirrorY) { - return drawSprite(x, y, &rect, 100, 100, alpha, false, blendMode, mirrorX, mirrorY); -} - -////////////////////////////////////////////////////////////////////////// -bool BaseSurfaceOSystem::displayTransOffset(int x, int y, Rect32 rect, uint32 alpha, TSpriteBlendMode blendMode, bool mirrorX, bool mirrorY, int offsetX, int offsetY) { - return drawSprite(x, y, &rect, 100, 100, alpha, false, blendMode, mirrorX, mirrorY, offsetX, offsetY); -} - -////////////////////////////////////////////////////////////////////////// -bool BaseSurfaceOSystem::displayTransZoom(int x, int y, Rect32 rect, float zoomX, float zoomY, uint32 alpha, TSpriteBlendMode blendMode, bool mirrorX, bool mirrorY) { - return drawSprite(x, y, &rect, zoomX, zoomY, alpha, false, blendMode, mirrorX, mirrorY); -} - - -////////////////////////////////////////////////////////////////////////// -bool BaseSurfaceOSystem::displayZoom(int x, int y, Rect32 rect, float zoomX, float zoomY, uint32 alpha, bool transparent, TSpriteBlendMode blendMode, bool mirrorX, bool mirrorY) { - return drawSprite(x, y, &rect, zoomX, zoomY, alpha, !transparent, blendMode, mirrorX, mirrorY); -} - - -////////////////////////////////////////////////////////////////////////// -bool BaseSurfaceOSystem::displayTransform(int x, int y, int hotX, int hotY, Rect32 rect, float zoomX, float zoomY, uint32 alpha, float rotate, TSpriteBlendMode blendMode, bool mirrorX, bool mirrorY) { - return drawSprite(x, y, &rect, zoomX, zoomY, alpha, false, blendMode, mirrorX, mirrorY); -} - -////////////////////////////////////////////////////////////////////////// -bool BaseSurfaceOSystem::drawSprite(int x, int y, Rect32 *rect, float zoomX, float zoomY, uint32 alpha, bool alphaDisable, TSpriteBlendMode blendMode, bool mirrorX, bool mirrorY, int offsetX, int offsetY) { - BaseRenderOSystem *renderer = static_cast(_gameRef->_renderer); - - if (!_loaded) { - finishLoad(); - } - - if (renderer->_forceAlphaColor != 0) { - alpha = renderer->_forceAlphaColor; - } - - byte r = RGBCOLGetR(alpha); - byte g = RGBCOLGetG(alpha); - byte b = RGBCOLGetB(alpha); - byte a = RGBCOLGetA(alpha); - - renderer->setAlphaMod(a); - renderer->setColorMod(r, g, b); - -#if 0 // These are kept for reference if BlendMode is reimplemented at some point. - if (alphaDisable) { - SDL_SetTextureBlendMode(_texture, SDL_BLENDMODE_NONE); - } else { - SDL_SetTextureBlendMode(_texture, SDL_BLENDMODE_BLEND); - } -#endif - // TODO: This _might_ miss the intended behaviour by 1 in each direction - // But I think it fits the model used in Wintermute. - Common::Rect srcRect; - srcRect.left = rect->left; - srcRect.top = rect->top; - srcRect.setWidth(rect->right - rect->left); - srcRect.setHeight(rect->bottom - rect->top); - - Common::Rect position; - position.left = x + offsetX; - position.top = y + offsetY; - - // Crop off-by-ones: - if (position.left == -1) { - position.left = 0; // TODO: Something is wrong - } - if (position.top == -1) { - position.top = 0; // TODO: Something is wrong - } - - position.setWidth((int16)((float)srcRect.width() * zoomX / 100.f)); - position.setHeight((int16)((float)srcRect.height() * zoomX / 100.f)); - - renderer->modTargetRect(&position); - - /* position.left += offsetX; - position.top += offsetY;*/ - - // TODO: This actually requires us to have the SAME source-offsets every time, - // But no checking is in place for that yet. - - // TODO: Optimize by not doing alpha-blits if we lack or disable alpha - bool hasAlpha; - if (_hasAlpha && !alphaDisable) { - hasAlpha = true; - } else { - hasAlpha = false; - } - if (alphaDisable) { - warning("BaseSurfaceOSystem::drawSprite - AlphaDisable ignored"); - } - - renderer->drawSurface(this, _surface, &srcRect, &position, mirrorX, mirrorY, !hasAlpha); - - return STATUS_OK; -} - -bool BaseSurfaceOSystem::putSurface(const Graphics::Surface &surface, bool hasAlpha) { - _loaded = true; - _surface->free(); - _surface->copyFrom(surface); - _hasAlpha = hasAlpha; - BaseRenderOSystem *renderer = static_cast(_gameRef->_renderer); - renderer->invalidateTicketsFromSurface(this); - - return STATUS_OK; -} - -} // end of namespace Wintermute +/* 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. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#include "engines/wintermute/base/file/base_file.h" +#include "engines/wintermute/base/base_file_manager.h" +#include "engines/wintermute/base/base_game.h" +#include "engines/wintermute/base/gfx/osystem/base_surface_osystem.h" +#include "engines/wintermute/base/gfx/osystem/base_render_osystem.h" +#include "engines/wintermute/base/gfx/base_image.h" +#include "engines/wintermute/platform_osystem.h" +#include "graphics/decoders/png.h" +#include "graphics/decoders/bmp.h" +#include "graphics/decoders/jpeg.h" +#include "graphics/decoders/tga.h" +#include "engines/wintermute/graphics/transparent_surface.h" +#include "graphics/pixelformat.h" +#include "graphics/surface.h" +#include "common/stream.h" +#include "common/system.h" + +namespace Wintermute { + +////////////////////////////////////////////////////////////////////////// +BaseSurfaceOSystem::BaseSurfaceOSystem(BaseGame *inGame) : BaseSurface(inGame) { + _surface = new Graphics::Surface(); + _alphaMask = NULL; + _hasAlpha = true; + _lockPixels = NULL; + _lockPitch = 0; + _loaded = false; +} + +////////////////////////////////////////////////////////////////////////// +BaseSurfaceOSystem::~BaseSurfaceOSystem() { + if (_surface) { + _surface->free(); + delete _surface; + _surface = NULL; + } + + delete[] _alphaMask; + _alphaMask = NULL; + + _gameRef->addMem(-_width * _height * 4); + BaseRenderOSystem *renderer = static_cast(_gameRef->_renderer); + renderer->invalidateTicketsFromSurface(this); +} + +bool hasTransparency(Graphics::Surface *surf) { + if (surf->format.bytesPerPixel != 4) { + warning("hasTransparency:: non 32 bpp surface passed as argument"); + return false; + } + uint8 r, g, b, a; + for (int i = 0; i < surf->h; i++) { + for (int j = 0; j < surf->w; j++) { + uint32 pix = *(uint32 *)surf->getBasePtr(j, i); + surf->format.colorToARGB(pix, a, r, g, b); + if (a != 255) { + return true; + } + } + } + return false; +} + +////////////////////////////////////////////////////////////////////////// +bool BaseSurfaceOSystem::create(const Common::String &filename, bool defaultCK, byte ckRed, byte ckGreen, byte ckBlue, int lifeTime, bool keepLoaded) { + /* BaseRenderOSystem *renderer = static_cast(_gameRef->_renderer); */ + _filename = filename; +// const Graphics::Surface *surface = image->getSurface(); + + if (defaultCK) { + ckRed = 255; + ckGreen = 0; + ckBlue = 255; + } + + _ckDefault = defaultCK; + _ckRed = ckRed; + _ckGreen = ckGreen; + _ckBlue = ckBlue; + + if (_lifeTime == 0 || lifeTime == -1 || lifeTime > _lifeTime) { + _lifeTime = lifeTime; + } + + _keepLoaded = keepLoaded; + if (_keepLoaded) { + _lifeTime = -1; + } + + return STATUS_OK; +} + +bool BaseSurfaceOSystem::finishLoad() { + BaseImage *image = new BaseImage(); + if (!image->loadFile(_filename)) { + return false; + } + + _width = image->getSurface()->w; + _height = image->getSurface()->h; + + bool isSaveGameGrayscale = scumm_strnicmp(_filename.c_str(), "savegame:", 9) == 0 && (_filename.c_str()[_filename.size() - 1] == 'g' || _filename.c_str()[_filename.size() - 1] == 'G'); + if (isSaveGameGrayscale) { + warning("grayscaleConversion not yet implemented"); + // FIBITMAP *newImg = FreeImage_ConvertToGreyscale(img); TODO + } + + // no alpha, set color key + /* if (surface->format.bytesPerPixel != 4) + SDL_SetColorKey(surf, SDL_TRUE, SDL_MapRGB(surf->format, ck_red, ck_green, ck_blue));*/ + + // convert 32-bit BMPs to 24-bit or they appear totally transparent (does any app actually write alpha in BMP properly?) + // Well, actually, we don't convert via 24-bit as the color-key application overwrites the Alpha-channel anyhow. + _surface->free(); + delete _surface; + if (_filename.hasSuffix(".bmp") && image->getSurface()->format.bytesPerPixel == 4) { + _surface = image->getSurface()->convertTo(g_system->getScreenFormat(), image->getPalette()); + TransparentSurface trans(*_surface); + trans.applyColorKey(_ckRed, _ckGreen, _ckBlue); + } else if (image->getSurface()->format.bytesPerPixel == 1 && image->getPalette()) { + _surface = image->getSurface()->convertTo(g_system->getScreenFormat(), image->getPalette()); + TransparentSurface trans(*_surface); + trans.applyColorKey(_ckRed, _ckGreen, _ckBlue, true); + } else if (image->getSurface()->format.bytesPerPixel >= 3 && image->getSurface()->format != g_system->getScreenFormat()) { + _surface = image->getSurface()->convertTo(g_system->getScreenFormat()); + if (image->getSurface()->format.bytesPerPixel == 3) { + TransparentSurface trans(*_surface); + trans.applyColorKey(_ckRed, _ckGreen, _ckBlue, true); + } + } else { + _surface = new Graphics::Surface(); + _surface->copyFrom(*image->getSurface()); + } + + _hasAlpha = hasTransparency(_surface); + _valid = true; + + _gameRef->addMem(_width * _height * 4); + + delete image; + + _loaded = true; + + return true; +} + +////////////////////////////////////////////////////////////////////////// +void BaseSurfaceOSystem::genAlphaMask(Graphics::Surface *surface) { + warning("BaseSurfaceOSystem::GenAlphaMask - Not ported yet"); + return; + // TODO: Reimplement this + delete[] _alphaMask; + _alphaMask = NULL; + if (!surface) { + return; + } + + bool hasColorKey; + /* uint32 colorKey; */ + uint8 ckRed, ckGreen, ckBlue; + /* if (SDL_GetColorKey(surface, &colorKey) == 0) { + hasColorKey = true; + SDL_GetRGB(colorKey, surface->format, &ckRed, &ckGreen, &ckBlue); + } else hasColorKey = false; + */ + _alphaMask = new byte[surface->w * surface->h]; + + bool hasTransparency = false; + for (int y = 0; y < surface->h; y++) { + for (int x = 0; x < surface->w; x++) { + uint32 pixel = getPixelAt(surface, x, y); + + uint8 r, g, b, a; + surface->format.colorToARGB(pixel, a, r, g, b); + //SDL_GetRGBA(pixel, surface->format, &r, &g, &b, &a); + + if (hasColorKey && r == ckRed && g == ckGreen && b == ckBlue) { + a = 0; + } + + _alphaMask[y * surface->w + x] = a; + if (a < 255) { + hasTransparency = true; + } + } + } + + if (!hasTransparency) { + delete[] _alphaMask; + _alphaMask = NULL; + } +} + +////////////////////////////////////////////////////////////////////////// +uint32 BaseSurfaceOSystem::getPixelAt(Graphics::Surface *surface, int x, int y) { + warning("BaseSurfaceOSystem::GetPixel - Not ported yet"); + int bpp = surface->format.bytesPerPixel; + /* Here p is the address to the pixel we want to retrieve */ + uint8 *p = (uint8 *)surface->pixels + y * surface->pitch + x * bpp; + + switch (bpp) { + case 1: + return *p; + break; + + case 2: + return *(uint16 *)p; + break; + + case 3: +#ifdef SCUMM_BIG_ENDIAN + // if (SDL_BYTEORDER == SDL_BIG_ENDIAN) + return p[0] << 16 | p[1] << 8 | p[2]; +#else + //else + return p[0] | p[1] << 8 | p[2] << 16; +#endif + break; + + case 4: + return *(uint32 *)p; + break; + + default: + return 0; /* shouldn't happen, but avoids warnings */ + } + return 0; +} + +////////////////////////////////////////////////////////////////////////// +bool BaseSurfaceOSystem::create(int width, int height) { + _width = width; + _height = height; + + _gameRef->addMem(_width * _height * 4); + + _valid = true; + + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +bool BaseSurfaceOSystem::isTransparentAt(int x, int y) { + return isTransparentAtLite(x, y); +} + +////////////////////////////////////////////////////////////////////////// +bool BaseSurfaceOSystem::isTransparentAtLite(int x, int y) { + if (x < 0 || x >= _surface->w || y < 0 || y >= _surface->h) { + return true; + } + + if (_surface->format.bytesPerPixel == 4) { + uint32 pixel = *(uint32 *)_surface->getBasePtr(x, y); + uint8 r, g, b, a; + _surface->format.colorToARGB(pixel, a, r, g, b); + if (a <= 128) { + return true; + } else { + return false; + } + } + + return false; +} + +////////////////////////////////////////////////////////////////////////// +bool BaseSurfaceOSystem::startPixelOp() { + //SDL_LockTexture(_texture, NULL, &_lockPixels, &_lockPitch); + // Any pixel-op makes the caching useless: + BaseRenderOSystem *renderer = static_cast(_gameRef->_renderer); + renderer->invalidateTicketsFromSurface(this); + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +bool BaseSurfaceOSystem::endPixelOp() { + //SDL_UnlockTexture(_texture); + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool BaseSurfaceOSystem::display(int x, int y, Rect32 rect, TSpriteBlendMode blendMode, bool mirrorX, bool mirrorY) { + return drawSprite(x, y, &rect, 100, 100, 0xFFFFFFFF, true, blendMode, mirrorX, mirrorY); +} + + +////////////////////////////////////////////////////////////////////////// +bool BaseSurfaceOSystem::displayTrans(int x, int y, Rect32 rect, uint32 alpha, TSpriteBlendMode blendMode, bool mirrorX, bool mirrorY) { + return drawSprite(x, y, &rect, 100, 100, alpha, false, blendMode, mirrorX, mirrorY); +} + +////////////////////////////////////////////////////////////////////////// +bool BaseSurfaceOSystem::displayTransOffset(int x, int y, Rect32 rect, uint32 alpha, TSpriteBlendMode blendMode, bool mirrorX, bool mirrorY, int offsetX, int offsetY) { + return drawSprite(x, y, &rect, 100, 100, alpha, false, blendMode, mirrorX, mirrorY, offsetX, offsetY); +} + +////////////////////////////////////////////////////////////////////////// +bool BaseSurfaceOSystem::displayTransZoom(int x, int y, Rect32 rect, float zoomX, float zoomY, uint32 alpha, TSpriteBlendMode blendMode, bool mirrorX, bool mirrorY) { + return drawSprite(x, y, &rect, zoomX, zoomY, alpha, false, blendMode, mirrorX, mirrorY); +} + + +////////////////////////////////////////////////////////////////////////// +bool BaseSurfaceOSystem::displayZoom(int x, int y, Rect32 rect, float zoomX, float zoomY, uint32 alpha, bool transparent, TSpriteBlendMode blendMode, bool mirrorX, bool mirrorY) { + return drawSprite(x, y, &rect, zoomX, zoomY, alpha, !transparent, blendMode, mirrorX, mirrorY); +} + + +////////////////////////////////////////////////////////////////////////// +bool BaseSurfaceOSystem::displayTransform(int x, int y, int hotX, int hotY, Rect32 rect, float zoomX, float zoomY, uint32 alpha, float rotate, TSpriteBlendMode blendMode, bool mirrorX, bool mirrorY) { + return drawSprite(x, y, &rect, zoomX, zoomY, alpha, false, blendMode, mirrorX, mirrorY); +} + +////////////////////////////////////////////////////////////////////////// +bool BaseSurfaceOSystem::drawSprite(int x, int y, Rect32 *rect, float zoomX, float zoomY, uint32 alpha, bool alphaDisable, TSpriteBlendMode blendMode, bool mirrorX, bool mirrorY, int offsetX, int offsetY) { + BaseRenderOSystem *renderer = static_cast(_gameRef->_renderer); + + if (!_loaded) { + finishLoad(); + } + + if (renderer->_forceAlphaColor != 0) { + alpha = renderer->_forceAlphaColor; + } + + byte r = RGBCOLGetR(alpha); + byte g = RGBCOLGetG(alpha); + byte b = RGBCOLGetB(alpha); + byte a = RGBCOLGetA(alpha); + + renderer->setAlphaMod(a); + renderer->setColorMod(r, g, b); + +#if 0 // These are kept for reference if BlendMode is reimplemented at some point. + if (alphaDisable) { + SDL_SetTextureBlendMode(_texture, SDL_BLENDMODE_NONE); + } else { + SDL_SetTextureBlendMode(_texture, SDL_BLENDMODE_BLEND); + } +#endif + // TODO: This _might_ miss the intended behaviour by 1 in each direction + // But I think it fits the model used in Wintermute. + Common::Rect srcRect; + srcRect.left = rect->left; + srcRect.top = rect->top; + srcRect.setWidth(rect->right - rect->left); + srcRect.setHeight(rect->bottom - rect->top); + + Common::Rect position; + position.left = x + offsetX; + position.top = y + offsetY; + + // Crop off-by-ones: + if (position.left == -1) { + position.left = 0; // TODO: Something is wrong + } + if (position.top == -1) { + position.top = 0; // TODO: Something is wrong + } + + position.setWidth((int16)((float)srcRect.width() * zoomX / 100.f)); + position.setHeight((int16)((float)srcRect.height() * zoomX / 100.f)); + + renderer->modTargetRect(&position); + + /* position.left += offsetX; + position.top += offsetY;*/ + + // TODO: This actually requires us to have the SAME source-offsets every time, + // But no checking is in place for that yet. + + // TODO: Optimize by not doing alpha-blits if we lack or disable alpha + bool hasAlpha; + if (_hasAlpha && !alphaDisable) { + hasAlpha = true; + } else { + hasAlpha = false; + } + if (alphaDisable) { + warning("BaseSurfaceOSystem::drawSprite - AlphaDisable ignored"); + } + + renderer->drawSurface(this, _surface, &srcRect, &position, mirrorX, mirrorY, !hasAlpha); + + return STATUS_OK; +} + +bool BaseSurfaceOSystem::putSurface(const Graphics::Surface &surface, bool hasAlpha) { + _loaded = true; + _surface->free(); + _surface->copyFrom(surface); + _hasAlpha = hasAlpha; + BaseRenderOSystem *renderer = static_cast(_gameRef->_renderer); + renderer->invalidateTicketsFromSurface(this); + + return STATUS_OK; +} + +} // end of namespace Wintermute diff --git a/engines/wintermute/base/gfx/osystem/base_surface_osystem.h b/engines/wintermute/base/gfx/osystem/base_surface_osystem.h index b68fac4e3b..43422ef4e7 100644 --- a/engines/wintermute/base/gfx/osystem/base_surface_osystem.h +++ b/engines/wintermute/base/gfx/osystem/base_surface_osystem.h @@ -1,99 +1,99 @@ -/* 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. - * - */ - -/* - * This file is based on WME Lite. - * http://dead-code.org/redir.php?target=wmelite - * Copyright (c) 2011 Jan Nedoma - */ - -#ifndef WINTERMUTE_BASE_SURFACESDL_H -#define WINTERMUTE_BASE_SURFACESDL_H - -#include "graphics/surface.h" -#include "engines/wintermute/base/gfx/base_surface.h" -#include "common/list.h" - -namespace Wintermute { -struct TransparentSurface; -class BaseImage; -class BaseSurfaceOSystem : public BaseSurface { -public: - BaseSurfaceOSystem(BaseGame *inGame); - ~BaseSurfaceOSystem(); - - bool create(const Common::String &filename, bool defaultCK, byte ckRed, byte ckGreen, byte ckBlue, int lifeTime = -1, bool keepLoaded = false); - bool create(int width, int height); - - bool isTransparentAt(int x, int y); - bool isTransparentAtLite(int x, int y); - - bool startPixelOp(); - bool endPixelOp(); - - - bool displayTransZoom(int x, int y, Rect32 rect, float zoomX, float zoomY, uint32 alpha = 0xFFFFFFFF, TSpriteBlendMode blendMode = BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false); - bool displayTrans(int x, int y, Rect32 rect, uint32 alpha = 0xFFFFFFFF, TSpriteBlendMode blendMode = BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false); - bool displayTransOffset(int x, int y, Rect32 rect, uint32 alpha = 0xFFFFFFFF, TSpriteBlendMode blendMode = BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false, int offsetX = 0, int offsetY = 0); - bool display(int x, int y, Rect32 rect, TSpriteBlendMode blendMode = BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false); - bool displayZoom(int x, int y, Rect32 rect, float zoomX, float zoomY, uint32 alpha = 0xFFFFFFFF, bool transparent = false, TSpriteBlendMode blendMode = BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false); - bool displayTransform(int x, int y, int hotX, int hotY, Rect32 Rect, float zoomX, float zoomY, uint32 alpha, float rotate, TSpriteBlendMode blendMode = BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false); - virtual bool putSurface(const Graphics::Surface &surface, bool hasAlpha = false); - /* static unsigned DLL_CALLCONV ReadProc(void *buffer, unsigned size, unsigned count, fi_handle handle); - static int DLL_CALLCONV SeekProc(fi_handle handle, long offset, int origin); - static long DLL_CALLCONV TellProc(fi_handle handle);*/ - virtual int getWidth() { - if (!_loaded) { - finishLoad(); - } - if (_surface) { - return _surface->w; - } - return _width; - } - virtual int getHeight() { - if (!_loaded) { - finishLoad(); - } - if (_surface) { - return _surface->h; - } - return _height; - } - -private: - Graphics::Surface *_surface; - bool _loaded; - bool finishLoad(); - bool drawSprite(int x, int y, Rect32 *rect, float zoomX, float zoomY, uint32 alpha, bool alphaDisable, TSpriteBlendMode blendMode, bool mirrorX, bool mirrorY, int offsetX = 0, int offsetY = 0); - void genAlphaMask(Graphics::Surface *surface); - uint32 getPixelAt(Graphics::Surface *surface, int x, int y); - - bool _hasAlpha; - void *_lockPixels; - int _lockPitch; - byte *_alphaMask; -}; - -} // end of namespace Wintermute - -#endif +/* 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. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_BASE_SURFACESDL_H +#define WINTERMUTE_BASE_SURFACESDL_H + +#include "graphics/surface.h" +#include "engines/wintermute/base/gfx/base_surface.h" +#include "common/list.h" + +namespace Wintermute { +struct TransparentSurface; +class BaseImage; +class BaseSurfaceOSystem : public BaseSurface { +public: + BaseSurfaceOSystem(BaseGame *inGame); + ~BaseSurfaceOSystem(); + + bool create(const Common::String &filename, bool defaultCK, byte ckRed, byte ckGreen, byte ckBlue, int lifeTime = -1, bool keepLoaded = false); + bool create(int width, int height); + + bool isTransparentAt(int x, int y); + bool isTransparentAtLite(int x, int y); + + bool startPixelOp(); + bool endPixelOp(); + + + bool displayTransZoom(int x, int y, Rect32 rect, float zoomX, float zoomY, uint32 alpha = 0xFFFFFFFF, TSpriteBlendMode blendMode = BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false); + bool displayTrans(int x, int y, Rect32 rect, uint32 alpha = 0xFFFFFFFF, TSpriteBlendMode blendMode = BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false); + bool displayTransOffset(int x, int y, Rect32 rect, uint32 alpha = 0xFFFFFFFF, TSpriteBlendMode blendMode = BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false, int offsetX = 0, int offsetY = 0); + bool display(int x, int y, Rect32 rect, TSpriteBlendMode blendMode = BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false); + bool displayZoom(int x, int y, Rect32 rect, float zoomX, float zoomY, uint32 alpha = 0xFFFFFFFF, bool transparent = false, TSpriteBlendMode blendMode = BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false); + bool displayTransform(int x, int y, int hotX, int hotY, Rect32 Rect, float zoomX, float zoomY, uint32 alpha, float rotate, TSpriteBlendMode blendMode = BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false); + virtual bool putSurface(const Graphics::Surface &surface, bool hasAlpha = false); + /* static unsigned DLL_CALLCONV ReadProc(void *buffer, unsigned size, unsigned count, fi_handle handle); + static int DLL_CALLCONV SeekProc(fi_handle handle, long offset, int origin); + static long DLL_CALLCONV TellProc(fi_handle handle);*/ + virtual int getWidth() { + if (!_loaded) { + finishLoad(); + } + if (_surface) { + return _surface->w; + } + return _width; + } + virtual int getHeight() { + if (!_loaded) { + finishLoad(); + } + if (_surface) { + return _surface->h; + } + return _height; + } + +private: + Graphics::Surface *_surface; + bool _loaded; + bool finishLoad(); + bool drawSprite(int x, int y, Rect32 *rect, float zoomX, float zoomY, uint32 alpha, bool alphaDisable, TSpriteBlendMode blendMode, bool mirrorX, bool mirrorY, int offsetX = 0, int offsetY = 0); + void genAlphaMask(Graphics::Surface *surface); + uint32 getPixelAt(Graphics::Surface *surface, int x, int y); + + bool _hasAlpha; + void *_lockPixels; + int _lockPitch; + byte *_alphaMask; +}; + +} // end of namespace Wintermute + +#endif -- cgit v1.2.3