aboutsummaryrefslogtreecommitdiff
path: root/engines/wintermute/base/gfx
diff options
context:
space:
mode:
Diffstat (limited to 'engines/wintermute/base/gfx')
-rw-r--r--engines/wintermute/base/gfx/base_image.cpp269
-rw-r--r--engines/wintermute/base/gfx/base_image.h74
-rw-r--r--engines/wintermute/base/gfx/base_renderer.cpp257
-rw-r--r--engines/wintermute/base/gfx/base_renderer.h128
-rw-r--r--engines/wintermute/base/gfx/base_surface.cpp152
-rw-r--r--engines/wintermute/base/gfx/base_surface.h99
-rw-r--r--engines/wintermute/base/gfx/osystem/base_render_osystem.cpp701
-rw-r--r--engines/wintermute/base/gfx/osystem/base_render_osystem.h129
-rw-r--r--engines/wintermute/base/gfx/osystem/base_surface_osystem.cpp532
-rw-r--r--engines/wintermute/base/gfx/osystem/base_surface_osystem.h101
10 files changed, 2442 insertions, 0 deletions
diff --git a/engines/wintermute/base/gfx/base_image.cpp b/engines/wintermute/base/gfx/base_image.cpp
new file mode 100644
index 0000000000..f1e27c9622
--- /dev/null
+++ b/engines/wintermute/base/gfx/base_image.cpp
@@ -0,0 +1,269 @@
+/* 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/dcgf.h"
+#include "engines/wintermute/base/gfx/base_image.h"
+#include "engines/wintermute/base/BGame.h"
+#include "engines/wintermute/base/BFileManager.h"
+#include "engines/wintermute/graphics/transparentSurface.h"
+#include "engines/wintermute/utils/StringUtil.h"
+#include "graphics/decoders/png.h"
+#include "graphics/decoders/jpeg.h"
+#include "graphics/decoders/bmp.h"
+#include "graphics/surface.h"
+#include "engines/wintermute/graphics/tga.h"
+#include "common/textconsole.h"
+#include "common/stream.h"
+#include "common/system.h"
+
+namespace WinterMute {
+
+//////////////////////////////////////////////////////////////////////
+CBImage::CBImage(CBGame *inGame, FIBITMAP *bitmap): CBBase(inGame) {
+#if 0
+ _bitmap = bitmap;
+#endif
+ _bitmap = NULL;
+ _palette = NULL;
+ _surface = NULL;
+ _decoder = NULL;
+ _deletableSurface = NULL;
+}
+
+
+//////////////////////////////////////////////////////////////////////
+CBImage::~CBImage() {
+ /* delete _bitmap; */
+ delete _decoder;
+ if (_deletableSurface) {
+ _deletableSurface->free();
+ }
+ delete _deletableSurface;
+#if 0
+ if (_bitmap) FreeImage_Unload(_bitmap);
+#endif
+}
+
+bool CBImage::loadFile(const Common::String &filename) {
+ _filename = filename;
+ _filename.toLowercase();
+ if (StringUtil::startsWith(filename, "savegame:", true)) {
+ _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 WinterMute::TGA();
+ } else if (_filename.hasSuffix(".jpg")) {
+ _decoder = new Graphics::JPEGDecoder();
+ } else {
+ error("CBImage::loadFile : Unsupported fileformat %s", filename.c_str());
+ }
+ _filename = filename;
+ Common::SeekableReadStream *file = _gameRef->_fileManager->openFile(filename.c_str());
+ if (!file) return STATUS_FAILED;
+
+ _decoder->loadStream(*file);
+ _surface = _decoder->getSurface();
+ _palette = _decoder->getPalette();
+ _gameRef->_fileManager->closeFile(file);
+
+ return STATUS_OK;
+}
+
+byte CBImage::getAlphaAt(int x, int y) {
+ if (!_surface) return 0xFF;
+ uint32 color = *(uint32 *)_surface->getBasePtr(x, y);
+ byte r, g, b, a;
+ _surface->format.colorToARGB(color, a, r, g, b);
+ return a;
+}
+
+void CBImage::copyFrom(Graphics::Surface *surface) {
+ _surface = _deletableSurface = new Graphics::Surface();
+ _deletableSurface->copyFrom(*surface);
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool CBImage::saveBMPFile(const char *filename) {
+#if 0
+ if (!_bitmap) return STATUS_FAILED;
+
+ if (FreeImage_Save(FIF_BMP, _bitmap, filename)) return STATUS_OK;
+ else return STATUS_FAILED;
+#endif
+ return STATUS_FAILED;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool CBImage::resize(int newWidth, int newHeight) {
+#if 0
+ if (!_bitmap) return STATUS_FAILED;
+
+ if (newWidth == 0) NewWidth = FreeImage_GetWidth(_bitmap);
+ if (newHeight == 0) NewHeight = FreeImage_GetHeight(_bitmap);
+
+
+ FIBITMAP *newImg = FreeImage_Rescale(_bitmap, NewWidth, NewHeight, FILTER_BILINEAR);
+ if (newImg) {
+ FreeImage_Unload(_bitmap);
+ _bitmap = newImg;
+ return STATUS_OK;
+ } else return STATUS_FAILED;
+#endif
+ return STATUS_FAILED;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool CBImage::writeBMPToStream(Common::WriteStream *stream) {
+ 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;
+
+ //*BufferSize = 0;
+#if 0
+ FIMEMORY *fiMem = FreeImage_OpenMemory();
+ FreeImage_SaveToMemory(FIF_PNG, _bitmap, fiMem);
+ uint32 size;
+ byte *data;
+ FreeImage_AcquireMemory(fiMem, &data, &size);
+
+
+ byte *Buffer = new byte[size];
+ memcpy(Buffer, data, size);
+
+ FreeImage_CloseMemory(fiMem);
+
+ if (BufferSize) *BufferSize = size;
+
+ return Buffer;
+#endif
+ return false;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool CBImage::copyFrom(CBImage *origImage, int newWidth, int newHeight) {
+#if 0
+ if (_bitmap) FreeImage_Unload(_bitmap);
+
+ if (NewWidth == 0) NewWidth = FreeImage_GetWidth(OrigImage->GetBitmap());
+ if (NewHeight == 0) NewHeight = FreeImage_GetHeight(OrigImage->GetBitmap());
+
+ _bitmap = FreeImage_Rescale(OrigImage->GetBitmap(), NewWidth, NewHeight, FILTER_BILINEAR);
+#endif
+ TransparentSurface temp(*origImage->_surface, false);
+ if (_deletableSurface) {
+ _deletableSurface->free();
+ delete _deletableSurface;
+ _deletableSurface = NULL;
+ }
+ _surface = _deletableSurface = temp.scale(newWidth, newHeight);
+ return STATUS_OK;
+}
+
+} // end of namespace WinterMute
diff --git a/engines/wintermute/base/gfx/base_image.h b/engines/wintermute/base/gfx/base_image.h
new file mode 100644
index 0000000000..646a9ddd2d
--- /dev/null
+++ b/engines/wintermute/base/gfx/base_image.h
@@ -0,0 +1,74 @@
+/* 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_BIMAGE_H
+#define WINTERMUTE_BIMAGE_H
+
+#include "engines/wintermute/base/BBase.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"
+
+struct FIBITMAP;
+
+namespace WinterMute {
+class CBSurface;
+class CBImage: CBBase {
+
+public:
+ CBImage(CBGame *inGame, FIBITMAP *bitmap = NULL);
+ ~CBImage();
+
+ 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);
+ bool writeBMPToStream(Common::WriteStream *stream);
+ bool resize(int newWidth, int newHeight);
+ bool saveBMPFile(const char *filename);
+ bool copyFrom(CBImage *origImage, int newWidth = 0, int newHeight = 0);
+ void copyFrom(Graphics::Surface *surface);
+private:
+ Common::String _filename;
+ Graphics::ImageDecoder *_decoder;
+ FIBITMAP *_bitmap;
+ const Graphics::Surface *_surface;
+ Graphics::Surface *_deletableSurface;
+ const byte *_palette;
+};
+
+} // end of namespace WinterMute
+
+#endif
diff --git a/engines/wintermute/base/gfx/base_renderer.cpp b/engines/wintermute/base/gfx/base_renderer.cpp
new file mode 100644
index 0000000000..010aca7141
--- /dev/null
+++ b/engines/wintermute/base/gfx/base_renderer.cpp
@@ -0,0 +1,257 @@
+/* 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/dcgf.h"
+#include "engines/wintermute/base/BActiveRect.h"
+#include "engines/wintermute/base/gfx/base_renderer.h"
+#include "engines/wintermute/base/gfx/base_surface.h"
+#include "engines/wintermute/base/BSubFrame.h"
+#include "engines/wintermute/base/BRegion.h"
+#include "engines/wintermute/PlatformSDL.h"
+
+namespace WinterMute {
+
+//////////////////////////////////////////////////////////////////////
+CBRenderer::CBRenderer(CBGame *inGame): CBBase(inGame) {
+ _window = 0;
+ _clipperWindow = 0;
+ _active = false;
+ _ready = false;
+ _windowed = true;
+ _forceAlphaColor = 0x00;
+
+ _width = _height = _bPP = 0;
+ CBPlatform::setRectEmpty(&_monitorRect);
+
+ _realWidth = _realHeight = 0;
+ _drawOffsetX = _drawOffsetY = 0;
+}
+
+
+//////////////////////////////////////////////////////////////////////
+CBRenderer::~CBRenderer() {
+ deleteRectList();
+ unclipCursor();
+}
+
+
+//////////////////////////////////////////////////////////////////////
+void CBRenderer::initLoop() {
+ deleteRectList();
+}
+
+
+//////////////////////////////////////////////////////////////////////
+CBObject *CBRenderer::getObjectAt(int x, int y) {
+ Point32 point;
+ point.x = x;
+ point.y = y;
+
+ for (int i = _rectList.getSize() - 1; i >= 0; i--) {
+ if (CBPlatform::ptInRect(&_rectList[i]->_rect, point)) {
+ if (_rectList[i]->_precise) {
+ // frame
+ if (_rectList[i]->_frame) {
+ int xx = (int)((_rectList[i]->_frame->_rect.left + x - _rectList[i]->_rect.left + _rectList[i]->_offsetX) / (float)((float)_rectList[i]->_zoomX / (float)100));
+ int yy = (int)((_rectList[i]->_frame->_rect.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->_rect.right - _rectList[i]->_frame->_rect.left;
+ xx = width - xx;
+ }
+
+ if (_rectList[i]->_frame->_mirrorY) {
+ int height = _rectList[i]->_frame->_rect.bottom - _rectList[i]->_frame->_rect.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 (CBObject *)NULL;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+void CBRenderer::deleteRectList() {
+ for (int i = 0; i < _rectList.getSize(); i++) {
+ delete _rectList[i];
+ }
+ _rectList.removeAll();
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////
+bool CBRenderer::switchFullscreen() {
+ return STATUS_FAILED;
+}
+
+//////////////////////////////////////////////////////////////////////
+bool CBRenderer::flip() {
+ return STATUS_FAILED;
+}
+
+
+//////////////////////////////////////////////////////////////////////
+bool CBRenderer::initRenderer(int width, int height, bool windowed) {
+ return STATUS_FAILED;
+}
+
+
+//////////////////////////////////////////////////////////////////////
+void CBRenderer::onWindowChange() {
+}
+
+
+//////////////////////////////////////////////////////////////////////
+bool CBRenderer::fill(byte r, byte g, byte b, Common::Rect *rect) {
+ return STATUS_FAILED;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool CBRenderer::windowedBlt() {
+ return STATUS_FAILED;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool CBRenderer::setup2D(bool Force) {
+ return STATUS_FAILED;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool CBRenderer::setupLines() {
+ return STATUS_FAILED;
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool CBRenderer::drawLine(int x1, int y1, int x2, int y2, uint32 color) {
+ return STATUS_FAILED;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool CBRenderer::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 CBRenderer::fade(uint16 alpha) {
+ return STATUS_FAILED;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool CBRenderer::fadeToColor(uint32 color, Common::Rect *rect) {
+ return STATUS_FAILED;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool CBRenderer::setViewport(int left, int top, int right, int bottom) {
+ return STATUS_FAILED;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool CBRenderer::setScreenViewport() {
+ return setViewport(_drawOffsetX, _drawOffsetY, _width + _drawOffsetX, _height + _drawOffsetY);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool CBRenderer::setViewport(Rect32 *rect) {
+ return setViewport(rect->left + _drawOffsetX,
+ rect->top + _drawOffsetY,
+ rect->right + _drawOffsetX,
+ rect->bottom + _drawOffsetY);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+CBImage *CBRenderer::takeScreenshot() {
+ return NULL;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool CBRenderer::clipCursor() {
+ /*
+ 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 CBRenderer::unclipCursor() {
+ /*
+ if (!_windowed) ::ClipCursor(NULL);
+ */
+ return STATUS_OK;
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool CBRenderer::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;
+}
+
+} // end of namespace WinterMute
diff --git a/engines/wintermute/base/gfx/base_renderer.h b/engines/wintermute/base/gfx/base_renderer.h
new file mode 100644
index 0000000000..81c13f8b39
--- /dev/null
+++ b/engines/wintermute/base/gfx/base_renderer.h
@@ -0,0 +1,128 @@
+/* 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_BRENDERER_H
+#define WINTERMUTE_BRENDERER_H
+
+
+#include "engines/wintermute/coll_templ.h"
+#include "engines/wintermute/base/BBase.h"
+#include "common/rect.h"
+
+namespace WinterMute {
+
+class CBImage;
+class CBActiveRect;
+class CBObject;
+class CBSurface;
+class CBRenderer: public CBBase {
+public:
+ int _realWidth;
+ int _realHeight;
+ int _drawOffsetX;
+ int _drawOffsetY;
+
+ virtual void dumpData(const char *filename) {};
+ virtual CBImage *takeScreenshot();
+ virtual bool setViewport(int left, int top, int right, int bottom);
+ virtual bool setViewport(Rect32 *Rect);
+ virtual bool setScreenViewport();
+ virtual bool fade(uint16 Alpha);
+ virtual bool fadeToColor(uint32 Color, Common::Rect *rect = NULL);
+ 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);
+ CBRenderer(CBGame *inGame = NULL);
+ virtual ~CBRenderer();
+ virtual bool setProjection() {
+ return STATUS_OK;
+ };
+
+ virtual bool windowedBlt();
+ virtual bool fill(byte r, byte g, byte b, Common::Rect *rect = NULL);
+ virtual void onWindowChange();
+ virtual bool initRenderer(int width, int height, bool windowed);
+ virtual bool flip();
+ virtual void initLoop();
+ virtual bool switchFullscreen();
+ virtual bool setup2D(bool force = false);
+ virtual bool setupLines();
+
+ virtual const char *getName() {
+ return "";
+ };
+ 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;
+ }
+
+ virtual CBSurface *createSurface() = 0;
+
+ bool clipCursor();
+ bool unclipCursor();
+
+ CBObject *getObjectAt(int x, int y);
+ void deleteRectList();
+
+ virtual bool startSpriteBatch() {
+ return STATUS_OK;
+ };
+ virtual bool endSpriteBatch() {
+ return STATUS_OK;
+ };
+ bool pointInViewport(Point32 *P);
+ uint32 _forceAlphaColor;
+ uint32 _window;
+ uint32 _clipperWindow;
+ bool _active;
+ bool _ready;
+ bool _windowed;
+ Rect32 _windowRect;
+ Rect32 _viewportRect;
+ Rect32 _screenRect;
+ Rect32 _monitorRect;
+ int _bPP;
+ int _height;
+ int _width;
+
+ CBArray<CBActiveRect *, CBActiveRect *> _rectList;
+};
+
+CBRenderer *makeOSystemRenderer(CBGame *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
new file mode 100644
index 0000000000..6c0ca40765
--- /dev/null
+++ b/engines/wintermute/base/gfx/base_surface.cpp
@@ -0,0 +1,152 @@
+/* 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/BGame.h"
+#include "engines/wintermute/base/gfx/base_surface.h"
+
+namespace WinterMute {
+
+//////////////////////////////////////////////////////////////////////
+CBSurface::CBSurface(CBGame *inGame): CBBase(inGame) {
+ _referenceCount = 0;
+
+ _width = _height = 0;
+
+ _filename = "";
+
+ _pixelOpReady = false;
+
+ _ckDefault = true;
+ _ckRed = _ckGreen = _ckBlue = 0;
+ _lifeTime = 0;
+ _keepLoaded = false;
+
+ _lastUsedTime = 0;
+ _valid = false;
+}
+
+
+//////////////////////////////////////////////////////////////////////
+CBSurface::~CBSurface() {
+ if (_pixelOpReady) endPixelOp();
+}
+
+
+//////////////////////////////////////////////////////////////////////
+bool CBSurface::create(const char *filename, bool defaultCK, byte ckRed, byte ckGreen, byte ckBlue, int lifeTime, bool keepLoaded) {
+ return STATUS_FAILED;
+}
+
+
+//////////////////////////////////////////////////////////////////////
+bool CBSurface::restore() {
+ return STATUS_FAILED;
+}
+
+//////////////////////////////////////////////////////////////////////
+bool CBSurface::isTransparentAt(int x, int y) {
+ return false;
+}
+
+//////////////////////////////////////////////////////////////////////
+bool CBSurface::displayHalfTrans(int x, int y, Rect32 rect) {
+ return STATUS_FAILED;
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool CBSurface::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 CBSurface::create(int Width, int Height) {
+ return STATUS_FAILED;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool CBSurface::startPixelOp() {
+ return STATUS_FAILED;
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool CBSurface::endPixelOp() {
+ return STATUS_FAILED;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool CBSurface::getPixel(int x, int y, byte *r, byte *g, byte *b, byte *a) {
+ return STATUS_FAILED;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool CBSurface::putPixel(int x, int y, byte r, byte g, byte b, int a) {
+ return STATUS_FAILED;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool CBSurface::comparePixel(int x, int y, byte r, byte g, byte b, int a) {
+ return false;
+}
+
+
+//////////////////////////////////////////////////////////////////////
+bool CBSurface::isTransparentAtLite(int x, int y) {
+ return false;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool CBSurface::invalidate() {
+ return STATUS_FAILED;
+}
+
+
+
+//////////////////////////////////////////////////////////////////////////
+bool CBSurface::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 CBSurface::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
new file mode 100644
index 0000000000..f5fbd495aa
--- /dev/null
+++ b/engines/wintermute/base/gfx/base_surface.h
@@ -0,0 +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_BSURFACE_H
+#define WINTERMUTE_BSURFACE_H
+
+#include "engines/wintermute/base/BBase.h"
+#include "engines/wintermute/math/Rect32.h"
+#include "graphics/surface.h"
+
+namespace WinterMute {
+
+class CBSurface: public CBBase {
+public:
+ virtual bool invalidate();
+ virtual bool prepareToDraw();
+ bool _ckDefault;
+ byte _ckRed;
+ byte _ckGreen;
+ byte _ckBlue;
+
+ uint32 _lastUsedTime;
+ bool _valid;
+ int _lifeTime;
+ bool _keepLoaded;
+
+ bool _pixelOpReady;
+ CBSurface(CBGame *inGame);
+ virtual ~CBSurface();
+
+ 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 char *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:
+ 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
new file mode 100644
index 0000000000..fc971357bf
--- /dev/null
+++ b/engines/wintermute/base/gfx/osystem/base_render_osystem.cpp
@@ -0,0 +1,701 @@
+/* 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/dcgf.h"
+#include "engines/wintermute/base/gfx/osystem/base_render_osystem.h"
+#include "engines/wintermute/base/BRegistry.h"
+#include "engines/wintermute/base/gfx/osystem/base_surface_osystem.h"
+#include "engines/wintermute/base/BSurfaceStorage.h"
+#include "engines/wintermute/base/gfx/base_image.h"
+#include "engines/wintermute/math/MathUtil.h"
+#include "engines/wintermute/base/BGame.h"
+#include "engines/wintermute/base/BSprite.h"
+#include "common/system.h"
+#include "engines/wintermute/graphics/transparentSurface.h"
+#include "common/queue.h"
+
+namespace WinterMute {
+
+RenderTicket::RenderTicket(CBSurfaceOSystem *owner, const Graphics::Surface *surf, Common::Rect *srcRect, Common::Rect *dstRect, bool mirrorX, bool mirrorY) : _owner(owner),
+ _srcRect(*srcRect), _dstRect(*dstRect), _drawNum(0), _isValid(true), _wantsDraw(true), _hasAlpha(true) {
+ _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;
+}
+
+CBRenderer *makeOSystemRenderer(CBGame *inGame) {
+ return new CBRenderOSystem(inGame);
+}
+
+// TODO: Redo everything here.
+
+//////////////////////////////////////////////////////////////////////////
+CBRenderOSystem::CBRenderOSystem(CBGame *inGame) : CBRenderer(inGame) {
+ _renderSurface = new Graphics::Surface();
+ _drawNum = 1;
+ _needsFlip = true;
+
+ _borderLeft = _borderRight = _borderTop = _borderBottom = 0;
+ _ratioX = _ratioY = 1.0f;
+ setAlphaMod(255);
+ setColorMod(255, 255, 255);
+ _dirtyRect = NULL;
+ _disableDirtyRects = true;
+}
+
+//////////////////////////////////////////////////////////////////////////
+CBRenderOSystem::~CBRenderOSystem() {
+ _renderSurface->free();
+ delete _renderSurface;
+#if 0
+ if (_renderer) SDL_DestroyRenderer(_renderer);
+ if (_win) SDL_DestroyWindow(_win);
+ SDL_Quit();
+#endif
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool CBRenderOSystem::initRenderer(int width, int height, bool windowed) {
+ //if (SDL_Init(SDL_INIT_VIDEO) < 0) return STATUS_FAILED;
+
+#if 0
+ SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 0);
+ SDL_GL_SetAttribute(SDL_GL_RETAINED_BACKING, 1);
+#endif
+ _width = width;
+ _height = height;
+ _renderRect.setWidth(_width);
+ _renderRect.setHeight(_height);
+
+ _realWidth = width;
+ _realHeight = height;
+
+
+ // find suitable resolution
+/*#ifdef __IPHONEOS__
+ _realWidth = 480;
+ _realHeight = 320;
+
+ int numModes = SDL_GetNumDisplayModes(0);
+ for (int i = 0; i < numModes; i++) {
+ SDL_DisplayMode mode;
+ SDL_GetDisplayMode(0, i, &mode);
+
+ if (mode.w > mode.h) {
+ _realWidth = mode.w;
+ _realHeight = mode.h;
+ break;
+ }
+ }
+#else*/
+ _realWidth = _gameRef->_registry->readInt("Debug", "ForceResWidth", _width);
+ _realHeight = _gameRef->_registry->readInt("Debug", "ForceResHeight", _height);
+//#endif
+
+ /*
+ _realWidth = 480;
+ _realHeight = 320;
+ */
+
+
+ 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;
+
+#if 0
+ Uint32 flags = SDL_WINDOW_SHOWN;
+#endif
+#ifdef __IPHONEOS__
+ //flags |= SDL_WINDOW_OPENGL | SDL_WINDOW_BORDERLESS;
+#endif
+
+ //_windowed = _gameRef->_registry->readBool("Video", "Windowed", true);
+// if (!windowed) flags |= SDL_WINDOW_FULLSCREEN;
+
+ Graphics::PixelFormat format(4, 8, 8, 8, 8, 24, 16, 8, 0);
+ 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;
+ }
+#if 0
+ _win = SDL_CreateWindow("WME Lite",
+ SDL_WINDOWPOS_UNDEFINED,
+ SDL_WINDOWPOS_UNDEFINED,
+ _realWidth, _realHeight,
+ flags);
+
+ if (!_win) return STATUS_FAILED;
+#endif
+
+ g_system->showMouse(false);
+
+#ifdef __IPHONEOS__
+ // SDL defaults to OGL ES2, which doesn't work on old devices
+ //SDL_SetHint(SDL_HINT_RENDER_DRIVER, "opengles");
+#else
+ //SDL_SetHint(SDL_HINT_RENDER_DRIVER, "opengl");
+#endif
+#if 0
+ _renderer = SDL_CreateRenderer(_win, -1, 0);
+
+ if (!_renderer) return STATUS_FAILED;
+#endif
+ _renderSurface->create(g_system->getWidth(), g_system->getHeight(), g_system->getScreenFormat());
+ _active = true;
+
+ _clearColor = _renderSurface->format.ARGBToColor(255, 0, 0, 0);
+
+ return STATUS_OK;
+}
+
+void CBRenderOSystem::setAlphaMod(byte alpha) {
+ byte r = RGBCOLGetR(_colorMod);
+ byte g = RGBCOLGetB(_colorMod);
+ byte b = RGBCOLGetB(_colorMod);
+ _colorMod = BS_ARGB(alpha, r, g, b);
+}
+
+void CBRenderOSystem::setColorMod(byte r, byte g, byte b) {
+ byte alpha = RGBCOLGetA(_colorMod);
+ _colorMod = BS_ARGB(alpha, r, g, b);
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool CBRenderOSystem::flip() {
+ if (!_disableDirtyRects) {
+ drawTickets();
+ }
+ 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 CBRenderOSystem::fill(byte r, byte g, byte b, Common::Rect *rect) {
+ //SDL_SetRenderDrawColor(_renderer, r, g, b, 0xFF);
+ //SDL_RenderClear(_renderer);
+ _clearColor = _renderSurface->format.ARGBToColor(0xFF, r, g, b);
+ if (!_disableDirtyRects)
+ return STATUS_OK;
+ if (!rect) {
+ rect = &_renderRect;
+ }
+ _renderSurface->fillRect(*rect, _clearColor);
+
+ return STATUS_OK;
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool CBRenderOSystem::fade(uint16 Alpha) {
+ uint32 dwAlpha = 255 - Alpha;
+ return fadeToColor(dwAlpha << 24);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool CBRenderOSystem::fadeToColor(uint32 Color, Common::Rect *rect) {
+ // This particular warning is rather messy, as this function is called a ton,
+ // thus we avoid printing it more than once.
+ static bool hasWarned = false;
+ if (!hasWarned) {
+ warning("CBRenderOSystem::FadeToColor - Breaks when using dirty rects");
+ warning("Implement CBRenderOSystem::FadeToColor"); // TODO.
+ hasWarned = true;
+ }
+
+ 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);
+
+ byte r = RGBCOLGetR(Color);
+ byte g = RGBCOLGetG(Color);
+ byte b = RGBCOLGetB(Color);
+ byte a = RGBCOLGetA(Color);
+
+ //TODO: This is only here until I'm sure about the final pixelformat
+ uint32 col = _renderSurface->format.ARGBToColor(a, r, g, b);
+ if (_disableDirtyRects)
+ _renderSurface->fillRect(fillRect, col);
+ else {
+ setAlphaMod(a);
+ setColorMod(r, g, b);
+ 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();
+ _clearColor = col;
+ }
+ //SDL_SetRenderDrawColor(_renderer, r, g, b, a);
+ //SDL_SetRenderDrawBlendMode(_renderer, SDL_BLENDMODE_BLEND);
+ //SDL_RenderFillRect(_renderer, &fillRect);
+
+ return STATUS_OK;
+}
+
+void CBRenderOSystem::drawSurface(CBSurfaceOSystem *owner, const Graphics::Surface *surf, Common::Rect *srcRect, Common::Rect *dstRect, bool mirrorX, bool mirrorY) {
+ if (_disableDirtyRects) {
+ RenderTicket renderTicket(owner, surf, srcRect, dstRect, mirrorX, mirrorY);
+ // HINT: The surface-data contains other info than it should.
+ // drawFromSurface(renderTicket._surface, srcRect, dstRect, NULL, mirrorX, mirrorY);
+ drawFromSurface(renderTicket._surface, &renderTicket._srcRect, &renderTicket._dstRect, NULL, renderTicket._mirror);
+ return;
+ }
+ // Skip rects that are completely outside the screen:
+ if ((dstRect->left < 0 && dstRect->right < 0) || (dstRect->top < 0 && dstRect->bottom < 0)) {
+ return;
+ }
+
+ RenderTicket compare(owner, NULL, srcRect, dstRect, mirrorX, mirrorY);
+ compare._colorMod = _colorMod;
+ RenderQueueIterator it;
+ for (it = _renderQueue.begin(); it != _renderQueue.end(); it++) {
+ if ((*it)->_owner == owner && *(*it) == compare && (*it)->_isValid) {
+ (*it)->_colorMod = _colorMod;
+ drawFromTicket(*it);
+ return;
+ }
+ }
+ RenderTicket *ticket = new RenderTicket(owner, surf, srcRect, dstRect, mirrorX, mirrorY);
+ ticket->_colorMod = _colorMod;
+ drawFromTicket(ticket);
+}
+
+void CBRenderOSystem::invalidateTicket(RenderTicket *renderTicket) {
+ addDirtyRect(renderTicket->_dstRect);
+ renderTicket->_isValid = false;
+// renderTicket->_canDelete = true; // TODO: Maybe readd this, to avoid even more duplicates.
+}
+
+void CBRenderOSystem::invalidateTicketsFromSurface(CBSurfaceOSystem *surf) {
+ RenderQueueIterator it;
+ for (it = _renderQueue.begin(); it != _renderQueue.end(); it++) {
+ if ((*it)->_owner == surf) {
+ invalidateTicket(*it);
+ }
+ }
+}
+
+void CBRenderOSystem::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<RenderTicket*>::iterator pos;
+ for (pos = _renderQueue.begin(); pos != _renderQueue.end(); pos++) {
+ if ((*pos)->_drawNum >= _drawNum) {
+ break;
+ }
+ }
+ _renderQueue.insert(pos, renderTicket);
+ Common::List<RenderTicket*>::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++;
+ }
+ }
+ // Is not in order, so readd it as if it was a new ticket
+ renderTicket->_drawNum = 0;
+ drawFromTicket(renderTicket);
+ }
+ }
+}
+
+void CBRenderOSystem::addDirtyRect(const Common::Rect &rect) {
+ if (!_dirtyRect) {
+ _dirtyRect = new Common::Rect(rect);
+ } else {
+ _dirtyRect->extend(rect);
+ }
+ _dirtyRect->clip(_renderRect);
+// warning("AddDirtyRect: %d %d %d %d", rect.left, rect.top, rect.right, rect.bottom);
+}
+
+void CBRenderOSystem::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);
+ //warning("Discarding Rect: %d %d %d %d Width: %d Height: %d", (*it)->_dstRect.left, (*it)->_dstRect.top, (*it)->_dstRect.right, (*it)->_dstRect.bottom, (*it)->_dstRect.width() , (*it)->_dstRect.height());
+ 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;
+// warning("DirtyRect: %d %d %d %d Width: %d Height: %d", _dirtyRect->left, _dirtyRect->top, _dirtyRect->right, _dirtyRect->bottom, _dirtyRect->width(), _dirtyRect->height());
+
+ // Apply the clear-color to the dirty rect.
+ _renderSurface->fillRect(*_dirtyRect, _clearColor);
+ for (it = _renderQueue.begin(); it != _renderQueue.end(); it++) {
+ RenderTicket *ticket = *it;
+ 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->_surface, &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 CBRenderOSystem::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 CBRenderOSystem::drawLine(int x1, int y1, int x2, int y2, uint32 color) {
+ static bool hasWarned = false;
+ if (!hasWarned) {
+ warning("CBRenderOSystem::DrawLine - not fully ported yet");
+ hasWarned = true;
+ }
+ 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;
+}
+
+//////////////////////////////////////////////////////////////////////////
+CBImage *CBRenderOSystem::takeScreenshot() {
+// TODO: Fix this
+ warning("CBRenderOSystem::TakeScreenshot() - not ported yet");
+ CBImage *screenshot = new CBImage(_gameRef);
+ screenshot->copyFrom(_renderSurface);
+ return screenshot;
+#if 0
+ SDL_Rect viewport;
+
+ SDL_RenderGetViewport(_renderer, &viewport);
+
+ SDL_Surface *surface = SDL_CreateRGBSurface(0, viewport.w, viewport.h, 24, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK, 0x00000000);
+ if (!surface) return NULL;
+
+ if (SDL_RenderReadPixels(_renderer, NULL, surface->format->format, surface->pixels, surface->pitch) < 0) return NULL;
+
+ FIBITMAP *dib = FreeImage_Allocate(viewport.w, viewport.h, 24, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK);
+
+ int bytespp = FreeImage_GetLine(dib) / FreeImage_GetWidth(dib);
+
+ for (unsigned y = 0; y < FreeImage_GetHeight(dib); y++) {
+ byte *bits = FreeImage_GetScanLine(dib, y);
+ byte *src = (byte *)surface->pixels + (viewport.h - y - 1) * surface->pitch;
+ memcpy(bits, src, bytespp * viewport.w);
+ }
+
+ return new CBImage(_gameRef, dib);
+#endif
+ return NULL;
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool CBRenderOSystem::switchFullscreen() {
+ /*if (_windowed) SDL_SetWindowFullscreen(_win, SDL_TRUE);
+ else SDL_SetWindowFullscreen(_win, SDL_FALSE);
+
+ _windowed = !_windowed;
+ */
+ _gameRef->_registry->writeBool("Video", "Windowed", _windowed);
+
+ return STATUS_OK;
+}
+
+//////////////////////////////////////////////////////////////////////////
+const char *CBRenderOSystem::getName() {
+ if (_name.empty()) {
+#if 0
+ if (_renderer) {
+ SDL_RendererInfo info;
+ SDL_GetRendererInfo(_renderer, &info);
+ _name = AnsiString(info.name);
+ }
+#endif
+ }
+ return _name.c_str();
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool CBRenderOSystem::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);
+
+ // TODO fix this once viewports work correctly in SDL/landscape
+#ifndef __IPHONEOS__
+ //SDL_RenderSetViewport(GetSdlRenderer(), &rect);
+#endif
+ return STATUS_OK;
+}
+
+//////////////////////////////////////////////////////////////////////////
+void CBRenderOSystem::modTargetRect(Common::Rect *rect) {
+#if 0
+ SDL_Rect viewportRect;
+ SDL_RenderGetViewport(GetSdlRenderer(), &viewportRect);
+
+ rect->x = MathUtil::Round(rect->x * _ratioX + _borderLeft - viewportRect.x);
+ rect->y = MathUtil::Round(rect->y * _ratioY + _borderTop - viewportRect.y);
+ rect->w = MathUtil::RoundUp(rect->w * _ratioX);
+ rect->h = MathUtil::RoundUp(rect->h * _ratioY);
+#endif
+}
+
+//////////////////////////////////////////////////////////////////////////
+void CBRenderOSystem::pointFromScreen(Point32 *point) {
+#if 0
+ SDL_Rect viewportRect;
+ SDL_RenderGetViewport(GetSdlRenderer(), &viewportRect);
+
+ point->x = point->x / _ratioX - _borderLeft / _ratioX + viewportRect.x;
+ point->y = point->y / _ratioY - _borderTop / _ratioY + viewportRect.y;
+#endif
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+void CBRenderOSystem::pointToScreen(Point32 *point) {
+#if 0
+ SDL_Rect viewportRect;
+ SDL_RenderGetViewport(GetSdlRenderer(), &viewportRect);
+
+ point->x = MathUtil::RoundUp(point->x * _ratioX) + _borderLeft - viewportRect.x;
+ point->y = MathUtil::RoundUp(point->y * _ratioY) + _borderTop - viewportRect.y;
+#endif
+}
+
+//////////////////////////////////////////////////////////////////////////
+void CBRenderOSystem::dumpData(const char *filename) {
+ warning("CBRenderOSystem::DumpData(%s) - not reimplemented yet", filename); // TODO
+#if 0
+ FILE *f = fopen(filename, "wt");
+ if (!f) return;
+
+ CBSurfaceStorage *Mgr = _gameRef->_surfaceStorage;
+
+ int TotalKB = 0;
+ int TotalLoss = 0;
+ fprintf(f, "Filename;Usage;Size;KBytes\n");
+ for (int i = 0; i < Mgr->_surfaces.getSize(); i++) {
+ CBSurfaceOSystem *Surf = (CBSurfaceOSystem *)Mgr->_surfaces[i];
+ if (!Surf->_filename) continue;
+ if (!Surf->_valid) continue;
+
+ fprintf(f, "%s;%d;", Surf->_filename, Surf->_referenceCount);
+ fprintf(f, "%dx%d;", Surf->getWidth(), Surf->getHeight());
+
+ int kb = Surf->getWidth() * Surf->getHeight() * 4 / 1024;
+
+ TotalKB += kb;
+ fprintf(f, "%d;", kb);
+ fprintf(f, "\n");
+ }
+ fprintf(f, "Total %d;;;%d\n", Mgr->_surfaces.getSize(), TotalKB);
+
+
+ fclose(f);
+ _gameRef->LOG(0, "Texture Stats Dump completed.");
+ _gameRef->QuickMessage("Texture Stats Dump completed.");
+#endif
+}
+
+CBSurface *CBRenderOSystem::createSurface() {
+ return new CBSurfaceOSystem(_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
new file mode 100644
index 0000000000..d41d14ef35
--- /dev/null
+++ b/engines/wintermute/base/gfx/osystem/base_render_osystem.h
@@ -0,0 +1,129 @@
+/* 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_BRENDERER_SDL_H
+#define WINTERMUTE_BRENDERER_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 CBSurfaceOSystem;
+class RenderTicket {
+public:
+ RenderTicket(CBSurfaceOSystem *owner, const Graphics::Surface *surf, Common::Rect *srcRect, Common::Rect *dstRest, bool mirrorX = false, bool mirrorY = false);
+ RenderTicket() : _isValid(true), _wantsDraw(false), _drawNum(0) {}
+ ~RenderTicket();
+ Graphics::Surface *_surface;
+ Common::Rect _srcRect;
+ Common::Rect _dstRect;
+ uint32 _mirror;
+ bool _hasAlpha;
+
+ bool _isValid;
+ bool _wantsDraw;
+ uint32 _drawNum;
+ uint32 _colorMod;
+
+ CBSurfaceOSystem *_owner;
+ bool operator==(RenderTicket &a);
+};
+
+class CBRenderOSystem : public CBRenderer {
+public:
+ CBRenderOSystem(CBGame *inGame);
+ ~CBRenderOSystem();
+
+ const char *getName();
+
+ bool initRenderer(int width, int height, bool windowed);
+ bool flip();
+ bool fill(byte r, byte g, byte b, Common::Rect *rect = NULL);
+
+ bool fade(uint16 alpha);
+ bool fadeToColor(uint32 color, Common::Rect *rect = NULL);
+
+ bool switchFullscreen();
+
+ bool drawLine(int x1, int y1, int x2, int y2, uint32 color);
+
+ CBImage *takeScreenshot();
+
+ void setAlphaMod(byte alpha);
+ void setColorMod(byte r, byte g, byte b);
+ void invalidateTicket(RenderTicket *renderTicket);
+ void invalidateTicketsFromSurface(CBSurfaceOSystem *surf);
+ void drawFromTicket(RenderTicket *renderTicket);
+
+ bool setViewport(int left, int top, int right, int bottom);
+
+ 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(CBSurfaceOSystem *owner, const Graphics::Surface *surf, Common::Rect *srcRect, Common::Rect *dstRect, bool mirrorX, bool mirrorY);
+ CBSurface *createSurface();
+private:
+ void addDirtyRect(const Common::Rect &rect);
+ void drawTickets();
+ void drawFromSurface(const Graphics::Surface *surf, Common::Rect *srcRect, Common::Rect *dstRect, Common::Rect *clipRect, uint32 mirror);
+ typedef Common::List<RenderTicket*>::iterator RenderQueueIterator;
+ Common::Rect *_dirtyRect;
+ Common::List<RenderTicket*> _renderQueue;
+ bool _needsFlip;
+ uint32 _drawNum;
+ Common::Rect _renderRect;
+ Graphics::Surface *_renderSurface;
+ AnsiString _name;
+
+ int _borderLeft;
+ int _borderTop;
+ int _borderRight;
+ int _borderBottom;
+
+ bool _disableDirtyRects;
+ float _ratioX;
+ float _ratioY;
+ uint32 _colorMod;
+ uint32 _clearColor;
+};
+
+} // end of namespace WinterMute
+
+#endif // WINTERMUTE_BRENDERER_SDL_H
diff --git a/engines/wintermute/base/gfx/osystem/base_surface_osystem.cpp b/engines/wintermute/base/gfx/osystem/base_surface_osystem.cpp
new file mode 100644
index 0000000000..1e4ac9a19e
--- /dev/null
+++ b/engines/wintermute/base/gfx/osystem/base_surface_osystem.cpp
@@ -0,0 +1,532 @@
+/* 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/BFile.h"
+#include "engines/wintermute/base/BFileManager.h"
+#include "engines/wintermute/base/BGame.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/PlatformSDL.h"
+#include "graphics/decoders/png.h"
+#include "graphics/decoders/bmp.h"
+#include "graphics/decoders/jpeg.h"
+#include "engines/wintermute/graphics/transparentSurface.h"
+#include "engines/wintermute/graphics/tga.h"
+#include "graphics/pixelformat.h"
+#include "graphics/surface.h"
+#include "common/stream.h"
+#include "common/system.h"
+
+namespace WinterMute {
+
+//////////////////////////////////////////////////////////////////////////
+CBSurfaceOSystem::CBSurfaceOSystem(CBGame *inGame) : CBSurface(inGame) {
+ _surface = new Graphics::Surface();
+ _alphaMask = NULL;
+ _hasAlpha = true;
+ _lockPixels = NULL;
+ _lockPitch = 0;
+ _loaded = false;
+}
+
+//////////////////////////////////////////////////////////////////////////
+CBSurfaceOSystem::~CBSurfaceOSystem() {
+ //TODO
+ if (_surface) {
+ _surface->free();
+ delete _surface;
+ _surface = NULL;
+ }
+
+ delete[] _alphaMask;
+ _alphaMask = NULL;
+
+ _gameRef->addMem(-_width * _height * 4);
+ CBRenderOSystem *renderer = static_cast<CBRenderOSystem *>(_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 CBSurfaceOSystem::create(const char *filename, bool defaultCK, byte ckRed, byte ckGreen, byte ckBlue, int lifeTime, bool keepLoaded) {
+ /* CBRenderOSystem *renderer = static_cast<CBRenderOSystem *>(_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;
+}
+
+void CBSurfaceOSystem::finishLoad() {
+ CBImage *image = new CBImage(_gameRef);
+ image->loadFile(_filename);
+
+ _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);
+ if (newImg) {
+ FreeImage_Unload(img);
+ img = newImg;
+ }*/
+ }
+
+ // 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.
+ 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 == 4 && image->getSurface()->format != g_system->getScreenFormat()) {
+ _surface = image->getSurface()->convertTo(g_system->getScreenFormat());
+ } else {
+ _surface = new Graphics::Surface();
+ _surface->copyFrom(*image->getSurface());
+ }
+
+ _hasAlpha = hasTransparency(_surface);
+ //SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "best"); //TODO
+ //_texture = SdlUtil::CreateTextureFromSurface(renderer->GetSdlRenderer(), surf);
+
+ // This particular warning is rather messy, as this function is called a ton,
+ // thus we avoid printing it more than once.
+ static bool hasWarned = false;
+ if (!hasWarned) {
+ warning("Surface-textures not fully ported yet");
+ hasWarned = true;
+ }
+ //delete imgDecoder;
+#if 0
+ _texture = SDL_CreateTextureFromSurface(renderer->GetSdlRenderer(), surf);
+ if (!_texture) {
+ SDL_FreeSurface(surf);
+ delete imgDecoder;
+ return STATUS_FAILED;
+ }
+
+ GenAlphaMask(surf);
+
+ SDL_FreeSurface(surf);
+ delete imgDecoder; // TODO: Update this if ImageDecoder doesn't end up owning the surface.
+#endif
+
+ _valid = true;
+
+ _gameRef->addMem(_width * _height * 4);
+
+ delete image;
+
+ _loaded = true;
+}
+
+//////////////////////////////////////////////////////////////////////////
+void CBSurfaceOSystem::genAlphaMask(Graphics::Surface *surface) {
+ warning("CBSurfaceOSystem::GenAlphaMask - Not ported yet");
+ return;
+
+ delete[] _alphaMask;
+ _alphaMask = NULL;
+ if (!surface) return;
+#if 0
+ SDL_LockSurface(surface);
+#endif
+ 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;
+ */ //TODO
+ _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 = getPixel(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 0
+ SDL_UnlockSurface(surface);
+#endif
+ if (!hasTransparency) {
+ delete[] _alphaMask;
+ _alphaMask = NULL;
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////
+uint32 CBSurfaceOSystem::getPixel(Graphics::Surface *surface, int x, int y) {
+ warning("CBSurfaceOSystem::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 CBSurfaceOSystem::create(int width, int height) {
+ warning("CBSurfaceOSystem::Create not ported yet"); //TODO
+#if 0
+ CBRenderOSystem *renderer = static_cast<CBRenderOSystem *>(_gameRef->_renderer);
+ _texture = SDL_CreateTexture(renderer->GetSdlRenderer(), SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, Width, Height);
+#endif
+ _width = width;
+ _height = height;
+
+ _gameRef->addMem(_width * _height * 4);
+
+ _valid = true;
+
+ return STATUS_OK;
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool CBSurfaceOSystem::createFromSDLSurface(Graphics::Surface *surface) {
+ warning("CBSurfaceOSystem::CreateFromSDLSurface not ported yet"); //TODO
+#if 0
+ CBRenderOSystem *renderer = static_cast<CBRenderOSystem *>(_gameRef->_renderer);
+ _texture = SDL_CreateTextureFromSurface(renderer->GetSdlRenderer(), surface);
+#endif
+ if (_surface) {
+ _surface->free();
+ delete _surface;
+ _surface = NULL;
+ }
+ _surface = new Graphics::Surface();
+ _surface->copyFrom(*surface);
+ _width = surface->w;
+ _height = surface->h;
+#if 0
+ _gameRef->AddMem(_width * _height * 4);
+#endif
+ _valid = true;
+
+ return STATUS_OK;
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool CBSurfaceOSystem::isTransparentAt(int x, int y) {
+ // This particular warning is rather messy, as this function is called a ton,
+ // thus we avoid printing it more than once.
+ static bool hasWarned = false;
+ if (!hasWarned) {
+ warning("CBSurfaceOSystem::IsTransparentAt not ported yet");
+ hasWarned = true;
+ }
+#if 0
+ int access;
+ int width, height;
+ //SDL_QueryTexture(_texture, NULL, &access, &width, &height); //TODO
+ //if (access != SDL_TEXTUREACCESS_STREAMING) return false;
+ if (X < 0 || X >= width || Y < 0 || Y >= height) return true;
+
+
+ StartPixelOp();
+ bool ret = isTransparentAtLite(X, Y);
+ EndPixelOp();
+
+ return ret;
+#endif
+ return 0;
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool CBSurfaceOSystem::isTransparentAtLite(int x, int y) {
+ //if (!_lockPixels) return false;
+
+ // This particular warning is rather messy, as this function is called a ton,
+ // thus we avoid printing it more than once.
+ static bool hasWarned = false;
+ if (!hasWarned) {
+ warning("CBSurfaceOSystem::IsTransparentAtLite not ported yet");
+ hasWarned = 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;
+ }
+ }
+#if 0
+ uint32 format;
+ int access;
+ int width, height;
+
+ //SDL_QueryTexture(_texture, &format, &access, &width, &height);
+ //if (access != SDL_TEXTUREACCESS_STREAMING) return false;
+ if (X < 0 || X >= width || Y < 0 || Y >= height) return true;
+
+ if (!_alphaMask) return false;
+ else return _alphaMask[Y * width + X] <= 128;
+#endif
+ return false;
+ /*
+ Uint32* dst = (Uint32*)((Uint8*)_lockPixels + Y * _lockPitch);
+ Uint32 pixel = dst[X];
+
+ SDL_PixelFormat* pixelFormat = SDL_AllocFormat(format);
+ Uint8 r, g, b, a;
+ SDL_GetRGBA(pixel, pixelFormat, &r, &g, &b, &a);
+ SDL_FreeFormat(pixelFormat);
+
+ return a <= 128;
+ */
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool CBSurfaceOSystem::startPixelOp() {
+ //SDL_LockTexture(_texture, NULL, &_lockPixels, &_lockPitch);
+ // Any pixel-op makes the caching useless:
+ CBRenderOSystem *renderer = static_cast<CBRenderOSystem *>(_gameRef->_renderer);
+ renderer->invalidateTicketsFromSurface(this);
+ return STATUS_OK;
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool CBSurfaceOSystem::endPixelOp() {
+ //SDL_UnlockTexture(_texture);
+ return STATUS_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool CBSurfaceOSystem::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 CBSurfaceOSystem::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 CBSurfaceOSystem::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 CBSurfaceOSystem::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 CBSurfaceOSystem::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 CBSurfaceOSystem::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 CBSurfaceOSystem::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) {
+ CBRenderOSystem *renderer = static_cast<CBRenderOSystem *>(_gameRef->_renderer);
+
+ if (!_loaded) {
+ finishLoad();
+ }
+
+ if (renderer->_forceAlphaColor != 0)
+ alpha = renderer->_forceAlphaColor;
+
+ // This particular warning is rather messy, as this function is called a ton,
+ // thus we avoid printing it more than once.
+ static bool hasWarned = false;
+ if (!hasWarned) {
+ warning("CBSurfaceOSystem::DrawSprite not fully ported yet"); // TODO.
+ hasWarned = true;
+ }
+
+ 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
+ SDL_SetTextureColorMod(_texture, r, g, b);
+ SDL_SetTextureAlphaMod(_texture, a);
+
+ 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;
+ // TODO: Scaling...
+
+ 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.
+
+ bool hasAlpha;
+ if (_hasAlpha && !alphaDisable) {
+ hasAlpha = true;
+ } else {
+ hasAlpha = false;
+ }
+ if (alphaDisable) {
+ warning("CBSurfaceOSystem::drawSprite - AlphaDisable ignored");
+ }
+
+ renderer->drawSurface(this, _surface, &srcRect, &position, mirrorX, mirrorY);
+#if 0
+ SDL_RenderCopy(renderer->GetSdlRenderer(), _texture, &srcRect, &position);
+#endif
+
+ return STATUS_OK;
+}
+
+bool CBSurfaceOSystem::putSurface(const Graphics::Surface &surface, bool hasAlpha) {
+ _loaded = true;
+ _surface->copyFrom(surface);
+ _hasAlpha = hasAlpha;
+ CBRenderOSystem *renderer = static_cast<CBRenderOSystem *>(_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
new file mode 100644
index 0000000000..091e8ccba8
--- /dev/null
+++ b/engines/wintermute/base/gfx/osystem/base_surface_osystem.h
@@ -0,0 +1,101 @@
+/* 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_BSURFACESDL_H
+#define WINTERMUTE_BSURFACESDL_H
+
+#include "graphics/surface.h"
+#include "engines/wintermute/base/gfx/base_surface.h"
+#include "common/list.h"
+
+namespace WinterMute {
+struct TransparentSurface;
+class CBImage;
+class CBSurfaceOSystem : public CBSurface {
+public:
+ CBSurfaceOSystem(CBGame *inGame);
+ ~CBSurfaceOSystem();
+
+ bool create(const char *filename, bool defaultCK, byte ckRed, byte ckGreen, byte ckBlue, int lifeTime = -1, bool keepLoaded = false);
+ bool create(int width, int height);
+
+ bool createFromSDLSurface(Graphics::Surface *surface); //TODO: Rename function
+
+ 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;
+ void 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 getPixel(Graphics::Surface *surface, int x, int y);
+
+ bool _hasAlpha;
+ void *_lockPixels;
+ int _lockPitch;
+ byte *_alphaMask;
+};
+
+} // end of namespace WinterMute
+
+#endif // WINTERMUTE_BSURFACESDL_H