diff options
| author | Eugene Sandulenko | 2014-06-03 17:25:18 +0300 | 
|---|---|---|
| committer | Eugene Sandulenko | 2014-06-15 15:43:06 +0300 | 
| commit | 7322d905b37c222983e48219853aae105670e374 (patch) | |
| tree | 53d1b98a8fc62fedf9e60456416b8b4bfa25530a | |
| parent | 215f5f9a495c5072b398307bce12c940094b1d28 (diff) | |
| download | scummvm-rg350-7322d905b37c222983e48219853aae105670e374.tar.gz scummvm-rg350-7322d905b37c222983e48219853aae105670e374.tar.bz2 scummvm-rg350-7322d905b37c222983e48219853aae105670e374.zip  | |
COMMON: Copy TransparentSurface from Wintermute engine to common code
| -rw-r--r-- | graphics/module.mk | 3 | ||||
| -rw-r--r-- | graphics/transform_struct.cpp | 120 | ||||
| -rw-r--r-- | graphics/transform_struct.h | 97 | ||||
| -rw-r--r-- | graphics/transform_tools.cpp | 87 | ||||
| -rw-r--r-- | graphics/transform_tools.h | 77 | ||||
| -rw-r--r-- | graphics/transparent_surface.cpp | 851 | ||||
| -rw-r--r-- | graphics/transparent_surface.h | 152 | 
7 files changed, 1387 insertions, 0 deletions
diff --git a/graphics/module.mk b/graphics/module.mk index 5918775240..2705322c79 100644 --- a/graphics/module.mk +++ b/graphics/module.mk @@ -17,6 +17,9 @@ MODULE_OBJS := \  	scaler/thumbnail_intern.o \  	sjis.o \  	surface.o \ +	transform_struct.o \ +	transform_tools.o \ +	transparent_surface.o \  	thumbnail.o \  	VectorRenderer.o \  	VectorRendererSpec.o \ diff --git a/graphics/transform_struct.cpp b/graphics/transform_struct.cpp new file mode 100644 index 0000000000..a6beada17f --- /dev/null +++ b/graphics/transform_struct.cpp @@ -0,0 +1,120 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "graphics/transform_struct.h" +#include "graphics/transparent_surface.h" + +namespace Graphics { + +void TransformStruct::init(Common::Point zoom, uint32 angle, Common::Point hotspot, bool alphaDisable, TSpriteBlendMode blendMode, uint32 rgbaMod, bool mirrorX, bool mirrorY, Common::Point offset) { +	_zoom = zoom; +	_angle = angle; +	_hotspot = hotspot; +	_blendMode = blendMode; +	_rgbaMod = rgbaMod; +	_alphaDisable = alphaDisable; +	_flip = 0; +	_flip += FLIP_H * mirrorX; +	_flip += FLIP_V * mirrorY; +	_offset = offset; +	_numTimesX = 1; +	_numTimesY = 1; +} + +TransformStruct::TransformStruct(int32 zoomX, int32 zoomY, uint32 angle, int32 hotspotX, int32 hotspotY, TSpriteBlendMode blendMode, uint32 rgbaMod, bool mirrorX, bool mirrorY, int32 offsetX, int32 offsetY) { +	init(Common::Point(zoomX, zoomY), +		angle, +		Common::Point(hotspotX, hotspotY), +		false, +		blendMode, +		rgbaMod, +		mirrorX, mirrorY, +		Common::Point(offsetX, offsetY)); +} + +TransformStruct::TransformStruct(float zoomX, float zoomY, uint32 angle, int32 hotspotX, int32 hotspotY, TSpriteBlendMode blendMode, uint32 rgbaMod, bool mirrorX, bool mirrorY, int32 offsetX, int32 offsetY) { +	init(Common::Point((int)(zoomX / 100.0 * kDefaultZoomX), +		     (int)(zoomY / 100.0 * kDefaultZoomY)), +		angle, +		Common::Point(hotspotX, hotspotY), +		false, +		blendMode, +		rgbaMod, +		mirrorX, mirrorY, +		Common::Point(offsetX, offsetY)); +} + +TransformStruct::TransformStruct(int32 zoomX, int32 zoomY, TSpriteBlendMode blendMode, uint32 rgbaMod, bool mirrorX, bool mirrorY) { +	init(Common::Point(zoomX, zoomY), +		kDefaultAngle, +		Common::Point(kDefaultHotspotX, kDefaultHotspotY), +		false, +		blendMode, +		rgbaMod, +		mirrorX, +		mirrorY, +		Common::Point(kDefaultOffsetX, kDefaultOffsetY)); +} + +TransformStruct::TransformStruct(int32 zoomX, int32 zoomY, uint32 angle, int32 hotspotX, int32 hotspotY) { +	init(Common::Point(zoomX, zoomY), +		angle, +		Common::Point(hotspotX, hotspotY), +		true, +		BLEND_NORMAL, +		kDefaultRgbaMod, +		false, false, +		Common::Point(kDefaultOffsetX, kDefaultOffsetY)); +} + +TransformStruct::TransformStruct(int32 numTimesX, int32 numTimesY) { +	init(Common::Point(kDefaultZoomX, kDefaultZoomY), +		kDefaultAngle, +		Common::Point(kDefaultHotspotX, kDefaultHotspotY), +		false, +		BLEND_NORMAL, +		kDefaultRgbaMod, +		false, false, +		Common::Point(kDefaultOffsetX, kDefaultOffsetY)); +	_numTimesX = numTimesX; +	_numTimesY = numTimesY; +} + +TransformStruct::TransformStruct() { +	init(Common::Point(kDefaultZoomX, kDefaultZoomY), +		kDefaultAngle, +		Common::Point(kDefaultHotspotX, kDefaultHotspotY), +		true, +		BLEND_NORMAL, +		kDefaultRgbaMod, +		false, false, +		Common::Point(kDefaultOffsetX, kDefaultOffsetY)); +} + +bool TransformStruct::getMirrorX() const { +	return (bool)(_flip & FLIP_H); +} + +bool TransformStruct::getMirrorY() const { +	return (bool)(_flip & FLIP_V); +} +} // End of namespace Graphics diff --git a/graphics/transform_struct.h b/graphics/transform_struct.h new file mode 100644 index 0000000000..640daf9f4c --- /dev/null +++ b/graphics/transform_struct.h @@ -0,0 +1,97 @@ +/* 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. + * + */ + +#ifndef GRAPHICS_TRANSFORM_STRUCT_H +#define GRAPHICS_TRANSFORM_STRUCT_H + +#include "common/rect.h" + +namespace Graphics { + +enum TSpriteBlendMode { +	BLEND_UNKNOWN       = -1, +	BLEND_NORMAL        = 0, +	BLEND_ADDITIVE      = 1, +	BLEND_SUBTRACTIVE   = 2, +	NUM_BLEND_MODES +}; + +/** + * Contains all the required information that define a transform. + * Same source sprite + same TransformStruct = Same resulting sprite. + * Has a number of overloaded constructors to accomodate various argument lists. + */ + +const int32 kDefaultZoomX = 100; +const int32 kDefaultZoomY = 100; +const uint32 kDefaultRgbaMod = 0xFFFFFFFF; +const int32 kDefaultHotspotX = 0; +const int32 kDefaultHotspotY = 0; +const int32 kDefaultOffsetX = 0; +const int32 kDefaultOffsetY = 0; +const int32 kDefaultAngle = 0;	 + +struct TransformStruct { +private: +	void init(Common::Point zoom, uint32 angle, Common::Point hotspot, bool alphaDisable, TSpriteBlendMode blendMode, uint32 alpha, bool mirrorX, bool mirrorY, Common::Point offset); + +public: +	TransformStruct(int32 zoomX, int32 zoomY, uint32 angle, int32 hotspotX, int32 hotspotY, TSpriteBlendMode blendMode, uint32 alpha, bool mirrorX = false, bool mirrorY = false, int32 offsetX = 0, int32 offsetY = 0); +	TransformStruct(float zoomX, float zoomY, uint32 angle, int32 hotspotX, int32 hotspotY, TSpriteBlendMode blendMode, uint32 alpha, bool mirrorX = false, bool mirrorY = false, int32 offsetX = 0, int32 offsetY = 0); +	TransformStruct(int32 zoomX, int32 zoomY, TSpriteBlendMode blendMode, uint32 alpha, bool mirrorX = false, bool mirrorY = false); +	TransformStruct(int32 zoomX, int32 zoomY, uint32 angle, int32 hotspotX = 0, int32 hotspotY = 0); +	TransformStruct(int32 numTimesX, int32 numTimesY); +	TransformStruct(); + +	Common::Point _zoom;   ///< Zoom; 100 = no zoom +	Common::Point _hotspot; ///< Position of the hotspot +	int32 _angle;   ///< Rotation angle, in degrees +	byte _flip;      ///< Bitflag: see TransparentSurface::FLIP_XXX +	bool _alphaDisable; +	TSpriteBlendMode _blendMode; +	uint32 _rgbaMod;      ///< RGBa +	Common::Point _offset; +	int32 _numTimesX; +	int32 _numTimesY; + +	bool getMirrorX() const; +	bool getMirrorY() const; + +	bool operator==(const TransformStruct &compare) const { +		return (compare._angle == _angle && +				compare._flip == _flip && +				compare._zoom == _zoom  && +				compare._offset == _offset && +				compare._alphaDisable == _alphaDisable  && +				compare._rgbaMod == _rgbaMod && +				compare._blendMode == _blendMode && +				compare._numTimesX == _numTimesX && +				compare._numTimesY == _numTimesY +			   ); +	} + +	bool operator!=(const TransformStruct &compare) const { +		return !(compare == *this); +	} +}; +} // End of namespace Graphics +#endif diff --git a/graphics/transform_tools.cpp b/graphics/transform_tools.cpp new file mode 100644 index 0000000000..6e87b6321a --- /dev/null +++ b/graphics/transform_tools.cpp @@ -0,0 +1,87 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + + +#include "graphics/transform_tools.h" +#include <math.h> + +namespace Graphics { + +FloatPoint TransformTools::transformPoint(FloatPoint point, const float rotate, const Common::Point &zoom, const bool mirrorX, const bool mirrorY) { +	float rotateRad = rotate * M_PI / 180.0f; +	float x = point.x; +	float y = point.y; +	x = (x * zoom.x) / kDefaultZoomX; +	y = (y * zoom.y) / kDefaultZoomY; +#if 0 +	// TODO: Mirroring should be done before rotation, but the blitting +	// code does the inverse, so we match that for now. +	if (mirrorX) +		x *= -1; +	if (mirrorY) +		y *= -1; +#endif +	FloatPoint newPoint; +	newPoint.x = x * cos(rotateRad) - y * sin(rotateRad); +	newPoint.y = x * sin(rotateRad) + y * cos(rotateRad); +	if (mirrorX) { +		newPoint.x *= -1; +	} +	if (mirrorY) { +		newPoint.y *= -1; +	} +	return newPoint; +} + +Common::Rect TransformTools::newRect(const Common::Rect &oldRect, const TransformStruct &transform, Common::Point *newHotspot) { +	Common::Point nw(oldRect.left, oldRect.top); +	Common::Point ne(oldRect.right, oldRect.top); +	Common::Point sw(oldRect.left, oldRect.bottom); +	Common::Point se(oldRect.right, oldRect.bottom); + +	FloatPoint nw1, ne1, sw1, se1; + +	nw1 = transformPoint(nw - transform._hotspot, transform._angle, transform._zoom); +	ne1 = transformPoint(ne - transform._hotspot, transform._angle, transform._zoom); +	sw1 = transformPoint(sw - transform._hotspot, transform._angle, transform._zoom); +	se1 = transformPoint(se - transform._hotspot, transform._angle, transform._zoom); + +	float top = MIN(nw1.y, MIN(ne1.y, MIN(sw1.y, se1.y))); +	float bottom = MAX(nw1.y, MAX(ne1.y, MAX(sw1.y, se1.y))); +	float left = MIN(nw1.x, MIN(ne1.x, MIN(sw1.x, se1.x))); +	float right = MAX(nw1.x, MAX(ne1.x, MAX(sw1.x, se1.x))); + +	if (newHotspot) { +		newHotspot->y = (uint32)(-floor(top)); +		newHotspot->x = (uint32)(-floor(left)); +	} + +	Common::Rect res; +	res.top = (int32)(floor(top)) + transform._hotspot.y; +	res.bottom = (int32)(ceil(bottom)) + transform._hotspot.y; +	res.left = (int32)(floor(left)) + transform._hotspot.x; +	res.right = (int32)(ceil(right)) + transform._hotspot.x; + +	return res; +} + +} // End of namespace Graphics diff --git a/graphics/transform_tools.h b/graphics/transform_tools.h new file mode 100644 index 0000000000..c618f7c35a --- /dev/null +++ b/graphics/transform_tools.h @@ -0,0 +1,77 @@ +/* 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. + * + */ + +#ifndef GRAPHICS_TRANSFORM_TOOLS_H +#define GRAPHICS_TRANSFORM_TOOLS_H + +#include "common/rect.h" +#include "graphics/transform_struct.h" + +namespace Graphics { + +	static const float kEpsilon = 0.00001;  // arbitrarily taken number + +	struct FloatPoint { +		float x; +		float y; +		FloatPoint() : x(0), y(0) {} +		FloatPoint(float x1, float y1) : x(x1), y(y1) {} +		FloatPoint(const Common::Point p) : x(p.x), y(p.y) {} +		bool operator==(const FloatPoint &p) const { return fabs(x - p.x) < kEpsilon && fabs(y - p.y) < kEpsilon; } +		bool operator!=(const FloatPoint  &p) const { return fabs(x - p.x) > kEpsilon || fabs(y - p.y) > kEpsilon; } +		FloatPoint operator+(const FloatPoint &delta) const { return FloatPoint (x + delta.x, y + delta.y);     } +		FloatPoint operator-(const FloatPoint &delta) const { return FloatPoint (x - delta.x, y - delta.y);     } + +		FloatPoint& operator+=(const FloatPoint &delta) { +			x += delta.x; +			y += delta.y; +			return *this; +		} +		FloatPoint& operator-=(const FloatPoint &delta) { +			x -= delta.x; +			y -= delta.y; +			return *this; +		} +	}; + +class TransformTools { +public: +	/** +	 * Basic transform (scale + rotate) for a single point +	 */ +	static FloatPoint transformPoint(FloatPoint point, const float rotate, const Common::Point &zoom, const bool mirrorX = false, const bool mirrorY = false); + +	/** +	 * @param &point the point on which the transform is to be applied +	 * @param rotate the angle in degrees +	 * @param &zoom  zoom x,y in percent +	 * @param mirrorX flip along the vertical axis? +	 * @param mirrorY flip along the horizontal axis? +	 * @return the smallest rect that can contain the transformed sprite +	 * and, as a side-effect, "newHotspot" will tell you where the hotspot will +	 * have ended up in the new rect, for centering. +	 */ +	static Common::Rect newRect(const Common::Rect &oldRect, const TransformStruct &transform, Common::Point *newHotspot); +}; + +} // End of namespace Wintermute +#endif diff --git a/graphics/transparent_surface.cpp b/graphics/transparent_surface.cpp new file mode 100644 index 0000000000..c2d334e731 --- /dev/null +++ b/graphics/transparent_surface.cpp @@ -0,0 +1,851 @@ +/* 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. + * + * + * The bottom part of this is file is adapted from SDL_rotozoom.c. The + * relevant copyright notice for those specific functions can be found at the + * top of that section. + * + */ + + + +#include "common/algorithm.h" +#include "common/endian.h" +#include "common/util.h" +#include "common/rect.h" +#include "common/math.h" +#include "common/textconsole.h" +#include "graphics/primitives.h" +#include "graphics/transparent_surface.h" +#include "graphics/transform_tools.h" + +//#define ENABLE_BILINEAR + +namespace Graphics { + +static const int kAShift = 0;//img->format.aShift; + +static const int kBModShift = 0;//img->format.bShift; +static const int kGModShift = 8;//img->format.gShift; +static const int kRModShift = 16;//img->format.rShift; +static const int kAModShift = 24;//img->format.aShift; + +#ifdef SCUMM_LITTLE_ENDIAN +static const int kAIndex = 0; +static const int kBIndex = 1; +static const int kGIndex = 2; +static const int kRIndex = 3; + +#else +static const int kAIndex = 3; +static const int kBIndex = 2; +static const int kGIndex = 1; +static const int kRIndex = 0; +#endif + +void doBlitOpaqueFast(byte *ino, byte *outo, uint32 width, uint32 height, uint32 pitch, int32 inStep, int32 inoStep); +void doBlitBinaryFast(byte *ino, byte *outo, uint32 width, uint32 height, uint32 pitch, int32 inStep, int32 inoStep); +void doBlitAlphaBlend(byte *ino, byte *outo, uint32 width, uint32 height, uint32 pitch, int32 inStep, int32 inoStep, uint32 color); +void doBlitAdditiveBlend(byte *ino, byte *outo, uint32 width, uint32 height, uint32 pitch, int32 inStep, int32 inoStep, uint32 color); +void doBlitSubtractiveBlend(byte *ino, byte *outo, uint32 width, uint32 height, uint32 pitch, int32 inStep, int32 inoStep, uint32 color); + +TransparentSurface::TransparentSurface() : Surface(), _alphaMode(ALPHA_FULL) {} + +TransparentSurface::TransparentSurface(const Surface &surf, bool copyData) : Surface(), _alphaMode(ALPHA_FULL) { +	if (copyData) { +		copyFrom(surf); +	} else { +		w = surf.w; +		h = surf.h; +		pitch = surf.pitch; +		format = surf.format; +		// We need to cast the const qualifier away here because 'pixels' +		// always needs to be writable. 'surf' however is a constant Surface, +		// thus getPixels will always return const pixel data. +		pixels = const_cast<void *>(surf.getPixels()); +	} +} + +/** + * Optimized version of doBlit to be used w/opaque blitting (no alpha). + */ +void doBlitOpaqueFast(byte *ino, byte *outo, uint32 width, uint32 height, uint32 pitch, int32 inStep, int32 inoStep) { + +	byte *in; +	byte *out; + +	for (uint32 i = 0; i < height; i++) { +		out = outo; +		in = ino; +		memcpy(out, in, width * 4); +		for (uint32 j = 0; j < width; j++) { +			out[kAIndex] = 0xFF; +			out += 4; +		} +		outo += pitch; +		ino += inoStep; +	} +} + +/** + * Optimized version of doBlit to be used w/binary blitting (blit or no-blit, no blending). + */ +void doBlitBinaryFast(byte *ino, byte *outo, uint32 width, uint32 height, uint32 pitch, int32 inStep, int32 inoStep) { + +	byte *in; +	byte *out; + +	for (uint32 i = 0; i < height; i++) { +		out = outo; +		in = ino; +		for (uint32 j = 0; j < width; j++) { +			uint32 pix = *(uint32 *)in; +			int a = (pix >> kAShift) & 0xff; + +			if (a != 0) {   // Full opacity (Any value not exactly 0 is Opaque here) +				*(uint32 *)out = pix; +				out[kAIndex] = 0xFF; +			} +			out += 4; +			in += inStep; +		} +		outo += pitch; +		ino += inoStep; +	} +} + +/** + * Optimized version of doBlit to be used with alpha blended blitting + * @param ino a pointer to the input surface + * @param outo a pointer to the output surface + * @param width width of the input surface + * @param height height of the input surface + * @param pitch pitch of the output surface - that is, width in bytes of every row, usually bpp * width of the TARGET surface (the area we are blitting to might be smaller, do the math) + * @inStep size in bytes to skip to address each pixel, usually bpp of the source surface + * @inoStep width in bytes of every row on the *input* surface / kind of like pitch + * @color colormod in 0xAARRGGBB format - 0xFFFFFFFF for no colormod + */ +void doBlitAlphaBlend(byte *ino, byte *outo, uint32 width, uint32 height, uint32 pitch, int32 inStep, int32 inoStep, uint32 color) { +	byte *in; +	byte *out; + +	if (color == 0xffffffff) { + +		for (uint32 i = 0; i < height; i++) { +			out = outo; +			in = ino; +			for (uint32 j = 0; j < width; j++) { + +				if (in[kAIndex] != 0) { +					out[kAIndex] = 255; +					out[kRIndex] = ((in[kRIndex] * in[kAIndex]) + out[kRIndex] * (255 - in[kAIndex])) >> 8; +					out[kGIndex] = ((in[kGIndex] * in[kAIndex]) + out[kGIndex] * (255 - in[kAIndex])) >> 8; +					out[kBIndex] = ((in[kBIndex] * in[kAIndex]) + out[kBIndex] * (255 - in[kAIndex])) >> 8; +				} + +				in += inStep; +				out += 4; +			} +			outo += pitch; +			ino += inoStep; +		} +	} else { + +		byte ca = (color >> kAModShift) & 0xFF; +		byte cr = (color >> kRModShift) & 0xFF; +		byte cg = (color >> kGModShift) & 0xFF; +		byte cb = (color >> kBModShift) & 0xFF; + +		for (uint32 i = 0; i < height; i++) { +			out = outo; +			in = ino; +			for (uint32 j = 0; j < width; j++) { + +				uint32 ina = in[kAIndex] * ca >> 8; +				out[kAIndex] = 255; +				out[kBIndex] = (out[kBIndex] * (255 - ina) >> 8); +				out[kGIndex] = (out[kGIndex] * (255 - ina) >> 8); +				out[kRIndex] = (out[kRIndex] * (255 - ina) >> 8); + +				out[kBIndex] = out[kBIndex] + (in[kBIndex] * ina * cb >> 16); +				out[kGIndex] = out[kGIndex] + (in[kGIndex] * ina * cg >> 16); +				out[kRIndex] = out[kRIndex] + (in[kRIndex] * ina * cr >> 16); + +				in += inStep; +				out += 4; +			} +			outo += pitch; +			ino += inoStep; +		} +	} +} + +/** + * Optimized version of doBlit to be used with additive blended blitting + */ +void doBlitAdditiveBlend(byte *ino, byte *outo, uint32 width, uint32 height, uint32 pitch, int32 inStep, int32 inoStep, uint32 color) { +	byte *in; +	byte *out; + +	if (color == 0xffffffff) { + +		for (uint32 i = 0; i < height; i++) { +			out = outo; +			in = ino; +			for (uint32 j = 0; j < width; j++) { + +				if (in[kAIndex] != 0) { +					out[kRIndex] = MIN((in[kRIndex] * in[kAIndex] >> 8) + out[kRIndex], 255); +					out[kGIndex] = MIN((in[kGIndex] * in[kAIndex] >> 8) + out[kGIndex], 255); +					out[kBIndex] = MIN((in[kBIndex] * in[kAIndex] >> 8) + out[kBIndex], 255); +				} + +				in += inStep; +				out += 4; +			} +			outo += pitch; +			ino += inoStep; +		} +	} else { + +		byte ca = (color >> kAModShift) & 0xFF; +		byte cr = (color >> kRModShift) & 0xFF; +		byte cg = (color >> kGModShift) & 0xFF; +		byte cb = (color >> kBModShift) & 0xFF; + +		for (uint32 i = 0; i < height; i++) { +			out = outo; +			in = ino; +			for (uint32 j = 0; j < width; j++) { + +				uint32 ina = in[kAIndex] * ca >> 8; + +				if (cb != 255) { +					out[kBIndex] = MIN(out[kBIndex] + ((in[kBIndex] * cb * ina) >> 16), 255u); +				} else { +					out[kBIndex] = MIN(out[kBIndex] + (in[kBIndex] * ina >> 8), 255u); +				} + +				if (cg != 255) { +					out[kGIndex] = MIN(out[kGIndex] + ((in[kGIndex] * cg * ina) >> 16), 255u); +				} else { +					out[kGIndex] = MIN(out[kGIndex] + (in[kGIndex] * ina >> 8), 255u); +				} + +				if (cr != 255) { +					out[kRIndex] = MIN(out[kRIndex] + ((in[kRIndex] * cr * ina) >> 16), 255u); +				} else { +					out[kRIndex] = MIN(out[kRIndex] + (in[kRIndex] * ina >> 8), 255u); +				} + +				in += inStep; +				out += 4; +			} +			outo += pitch; +			ino += inoStep; +		} +	} +} + +/** + * Optimized version of doBlit to be used with subtractive blended blitting + */ +void doBlitSubtractiveBlend(byte *ino, byte *outo, uint32 width, uint32 height, uint32 pitch, int32 inStep, int32 inoStep, uint32 color) { +	byte *in; +	byte *out; + +	if (color == 0xffffffff) { + +		for (uint32 i = 0; i < height; i++) { +			out = outo; +			in = ino; +			for (uint32 j = 0; j < width; j++) { + +				if (in[kAIndex] != 0) { +					out[kRIndex] = MAX(out[kRIndex] - ((in[kRIndex] * out[kRIndex]) * in[kAIndex] >> 16), 0); +					out[kGIndex] = MAX(out[kGIndex] - ((in[kGIndex] * out[kGIndex]) * in[kAIndex] >> 16), 0); +					out[kBIndex] = MAX(out[kBIndex] - ((in[kBIndex] * out[kBIndex]) * in[kAIndex] >> 16), 0); +				} + +				in += inStep; +				out += 4; +			} +			outo += pitch; +			ino += inoStep; +		} +	} else { + +		byte cr = (color >> kRModShift) & 0xFF; +		byte cg = (color >> kGModShift) & 0xFF; +		byte cb = (color >> kBModShift) & 0xFF; + +		for (uint32 i = 0; i < height; i++) { +			out = outo; +			in = ino; +			for (uint32 j = 0; j < width; j++) { + +				out[kAIndex] = 255; +				if (cb != 255) { +					out[kBIndex] = MAX(out[kBIndex] - ((in[kBIndex] * cb  * (out[kBIndex]) * in[kAIndex]) >> 24), 0); +				} else { +					out[kBIndex] = MAX(out[kBIndex] - (in[kBIndex] * (out[kBIndex]) * in[kAIndex] >> 16), 0); +				} + +				if (cg != 255) { +					out[kGIndex] = MAX(out[kGIndex] - ((in[kGIndex] * cg  * (out[kGIndex]) * in[kAIndex]) >> 24), 0); +				} else { +					out[kGIndex] = MAX(out[kGIndex] - (in[kGIndex] * (out[kGIndex]) * in[kAIndex] >> 16), 0); +				} + +				if (cr != 255) { +					out[kRIndex] = MAX(out[kRIndex] - ((in[kRIndex] * cr * (out[kRIndex]) * in[kAIndex]) >> 24), 0); +				} else { +					out[kRIndex] = MAX(out[kRIndex] - (in[kRIndex] * (out[kRIndex]) * in[kAIndex] >> 16), 0); +				} + +				in += inStep; +				out += 4; +			} +			outo += pitch; +			ino += inoStep; +		} +	} +} + +Common::Rect TransparentSurface::blit(Graphics::Surface &target, int posX, int posY, int flipping, Common::Rect *pPartRect, uint color, int width, int height, TSpriteBlendMode blendMode) { + +	Common::Rect retSize; +	retSize.top = 0; +	retSize.left = 0; +	retSize.setWidth(0); +	retSize.setHeight(0); +	// Check if we need to draw anything at all +	int ca = (color >> 24) & 0xff; + +	if (ca == 0) { +		return retSize; +	} + +	// Create an encapsulating surface for the data +	TransparentSurface srcImage(*this, false); +	// TODO: Is the data really in the screen format? +	if (format.bytesPerPixel != 4) { +		warning("TransparentSurface can only blit 32bpp images, but got %d", format.bytesPerPixel * 8); +		return retSize; +	} + +	if (pPartRect) { + +		int xOffset = pPartRect->left; +		int yOffset = pPartRect->top; + +		if (flipping & FLIP_V) { +			yOffset = srcImage.h - pPartRect->bottom; +		} + +		if (flipping & FLIP_H) { +			xOffset = srcImage.w - pPartRect->right; +		} + +		srcImage.pixels = getBasePtr(xOffset, yOffset); +		srcImage.w = pPartRect->width(); +		srcImage.h = pPartRect->height(); + +		debug(6, "Blit(%d, %d, %d, [%d, %d, %d, %d], %08x, %d, %d)", posX, posY, flipping, +			  pPartRect->left,  pPartRect->top, pPartRect->width(), pPartRect->height(), color, width, height); +	} else { + +		debug(6, "Blit(%d, %d, %d, [%d, %d, %d, %d], %08x, %d, %d)", posX, posY, flipping, 0, 0, +			  srcImage.w, srcImage.h, color, width, height); +	} + +	if (width == -1) { +		width = srcImage.w; +	} +	if (height == -1) { +		height = srcImage.h; +	} + +#ifdef SCALING_TESTING +	// Hardcode scaling to 66% to test scaling +	width = width * 2 / 3; +	height = height * 2 / 3; +#endif + +	Graphics::Surface *img = nullptr; +	Graphics::Surface *imgScaled = nullptr; +	byte *savedPixels = nullptr; +	if ((width != srcImage.w) || (height != srcImage.h)) { +		// Scale the image +		img = imgScaled = srcImage.scale(width, height); +		savedPixels = (byte *)img->getPixels(); +	} else { +		img = &srcImage; +	} + +	// Handle off-screen clipping +	if (posY < 0) { +		img->h = MAX(0, (int)img->h - -posY); +		img->setPixels((byte *)img->getBasePtr(0, -posY)); +		posY = 0; +	} + +	if (posX < 0) { +		img->w = MAX(0, (int)img->w - -posX); +		img->setPixels((byte *)img->getBasePtr(-posX, 0)); +		posX = 0; +	} + +	img->w = CLIP((int)img->w, 0, (int)MAX((int)target.w - posX, 0)); +	img->h = CLIP((int)img->h, 0, (int)MAX((int)target.h - posY, 0)); + +	if ((img->w > 0) && (img->h > 0)) { +		int xp = 0, yp = 0; + +		int inStep = 4; +		int inoStep = img->pitch; +		if (flipping & FLIP_H) { +			inStep = -inStep; +			xp = img->w - 1; +		} + +		if (flipping & FLIP_V) { +			inoStep = -inoStep; +			yp = img->h - 1; +		} + +		byte *ino = (byte *)img->getBasePtr(xp, yp); +		byte *outo = (byte *)target.getBasePtr(posX, posY); + +		if (color == 0xFFFFFFFF && blendMode == BLEND_NORMAL && _alphaMode == ALPHA_OPAQUE) { +			doBlitOpaqueFast(ino, outo, img->w, img->h, target.pitch, inStep, inoStep); +		} else if (color == 0xFFFFFFFF && blendMode == BLEND_NORMAL && _alphaMode == ALPHA_BINARY) { +			doBlitBinaryFast(ino, outo, img->w, img->h, target.pitch, inStep, inoStep); +		} else { +			if (blendMode == BLEND_ADDITIVE) { +				doBlitAdditiveBlend(ino, outo, img->w, img->h, target.pitch, inStep, inoStep, color); +			} else if (blendMode == BLEND_SUBTRACTIVE) { +				doBlitSubtractiveBlend(ino, outo, img->w, img->h, target.pitch, inStep, inoStep, color); +			} else { +				assert(blendMode == BLEND_NORMAL); +				doBlitAlphaBlend(ino, outo, img->w, img->h, target.pitch, inStep, inoStep, color); +			} +		} + +	} + +	retSize.setWidth(img->w); +	retSize.setHeight(img->h); + +	if (imgScaled) { +		imgScaled->setPixels(savedPixels); +		imgScaled->free(); +		delete imgScaled; +	} + +	return retSize; +} + +/** + * Writes a color key to the alpha channel of the surface + * @param rKey  the red component of the color key + * @param gKey  the green component of the color key + * @param bKey  the blue component of the color key + * @param overwriteAlpha if true, all other alpha will be set fully opaque + */ +void TransparentSurface::applyColorKey(uint8 rKey, uint8 gKey, uint8 bKey, bool overwriteAlpha) { +	assert(format.bytesPerPixel == 4); +	for (int i = 0; i < h; i++) { +		for (int j = 0; j < w; j++) { +			uint32 pix = ((uint32 *)pixels)[i * w + j]; +			uint8 r, g, b, a; +			format.colorToARGB(pix, a, r, g, b); +			if (r == rKey && g == gKey && b == bKey) { +				a = 0; +				((uint32 *)pixels)[i * w + j] = format.ARGBToColor(a, r, g, b); +			} else if (overwriteAlpha) { +				a = 255; +				((uint32 *)pixels)[i * w + j] = format.ARGBToColor(a, r, g, b); +			} +		} +	} +} + +AlphaType TransparentSurface::getAlphaMode() const { +	return _alphaMode; +} + +void TransparentSurface::setAlphaMode(AlphaType mode) { +	_alphaMode = mode; +} + + + + + + +/* + +The below two functions are adapted from SDL_rotozoom.c, +taken from SDL_gfx-2.0.18. + +Its copyright notice: + +============================================================================= +SDL_rotozoom.c: rotozoomer, zoomer and shrinker for 32bit or 8bit surfaces + +Copyright (C) 2001-2012  Andreas Schiffler + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not +claim that you wrote the original software. If you use this software +in a product, an acknowledgment in the product documentation would be +appreciated but is not required. + +2. Altered source versions must be plainly marked as such, and must not be +misrepresented as being the original software. + +3. This notice may not be removed or altered from any source +distribution. + +Andreas Schiffler -- aschiffler at ferzkopp dot net +============================================================================= + + +The functions have been adapted for different structures and coordinate +systems. + +*/ + + + + + +TransparentSurface *TransparentSurface::rotoscale(const TransformStruct &transform) const { + +	assert(transform._angle != 0); // This would not be ideal; rotoscale() should never be called in conditional branches where angle = 0 anyway. + +	Common::Point newHotspot; +	Common::Rect srcRect(0, 0, (int16)w, (int16)h); +	Common::Rect rect = TransformTools::newRect(Common::Rect(srcRect), transform, &newHotspot); +	Common::Rect dstRect(0, 0, (int16)(rect.right - rect.left), (int16)(rect.bottom - rect.top)); + +	TransparentSurface *target = new TransparentSurface(); +	assert(format.bytesPerPixel == 4); + +	int srcW = w; +	int srcH = h; +	int dstW = dstRect.width(); +	int dstH = dstRect.height(); + +	target->create((uint16)dstW, (uint16)dstH, this->format); + +	if (transform._zoom.x == 0 || transform._zoom.y == 0) { +		return target; +	} + +	uint32 invAngle = 360 - (transform._angle % 360); +	float invCos = cos(invAngle * M_PI / 180.0); +	float invSin = sin(invAngle * M_PI / 180.0); + +	struct tColorRGBA { byte r; byte g; byte b; byte a; }; +	int icosx = (int)(invCos * (65536.0f * kDefaultZoomX / transform._zoom.x)); +	int isinx = (int)(invSin * (65536.0f * kDefaultZoomX / transform._zoom.x)); +	int icosy = (int)(invCos * (65536.0f * kDefaultZoomY / transform._zoom.y)); +	int isiny = (int)(invSin * (65536.0f * kDefaultZoomY / transform._zoom.y)); + + +	bool flipx = false, flipy = false; // TODO: See mirroring comment in RenderTicket ctor + +	int xd = (srcRect.left + transform._hotspot.x) << 16; +	int yd = (srcRect.top + transform._hotspot.y) << 16; +	int cx = newHotspot.x; +	int cy = newHotspot.y; + +	int ax = -icosx * cx; +	int ay = -isiny * cx; +	int sw = srcW - 1; +	int sh = srcH - 1; + +	tColorRGBA *pc = (tColorRGBA*)target->getBasePtr(0, 0); + +	for (int y = 0; y < dstH; y++) { +		int t = cy - y; +		int sdx = ax + (isinx * t) + xd; +		int sdy = ay - (icosy * t) + yd; +		for (int x = 0; x < dstW; x++) { +			int dx = (sdx >> 16); +			int dy = (sdy >> 16); +			if (flipx) { +				dx = sw - dx; +			} +			if (flipy) { +				dy = sh - dy; +			} + +#ifdef ENABLE_BILINEAR +			if ((dx > -1) && (dy > -1) && (dx < sw) && (dy < sh)) { +				const tColorRGBA *sp = (const tColorRGBA *)getBasePtr(dx, dy); +				tColorRGBA c00, c01, c10, c11, cswap; +				c00 = *sp; +				sp += 1; +				c01 = *sp; +				sp += (this->pitch / 4); +				c11 = *sp; +				sp -= 1; +				c10 = *sp; +				if (flipx) { +					cswap = c00; c00=c01; c01=cswap; +					cswap = c10; c10=c11; c11=cswap; +				} +				if (flipy) { +					cswap = c00; c00=c10; c10=cswap; +					cswap = c01; c01=c11; c11=cswap; +				} +				/* +				* Interpolate colors +				*/ +				int ex = (sdx & 0xffff); +				int ey = (sdy & 0xffff); +				int t1, t2; +				t1 = ((((c01.r - c00.r) * ex) >> 16) + c00.r) & 0xff; +				t2 = ((((c11.r - c10.r) * ex) >> 16) + c10.r) & 0xff; +				pc->r = (((t2 - t1) * ey) >> 16) + t1; +				t1 = ((((c01.g - c00.g) * ex) >> 16) + c00.g) & 0xff; +				t2 = ((((c11.g - c10.g) * ex) >> 16) + c10.g) & 0xff; +				pc->g = (((t2 - t1) * ey) >> 16) + t1; +				t1 = ((((c01.b - c00.b) * ex) >> 16) + c00.b) & 0xff; +				t2 = ((((c11.b - c10.b) * ex) >> 16) + c10.b) & 0xff; +				pc->b = (((t2 - t1) * ey) >> 16) + t1; +				t1 = ((((c01.a - c00.a) * ex) >> 16) + c00.a) & 0xff; +				t2 = ((((c11.a - c10.a) * ex) >> 16) + c10.a) & 0xff; +				pc->a = (((t2 - t1) * ey) >> 16) + t1; +			} +#else +			if ((dx >= 0) && (dy >= 0) && (dx < srcW) && (dy < srcH)) { +				const tColorRGBA *sp = (const tColorRGBA *)getBasePtr(dx, dy); +				*pc = *sp; +			} +#endif +			sdx += icosx; +			sdy += isiny; +			pc++; +		} +	} +	return target; +} + +TransparentSurface *TransparentSurface::scale(uint16 newWidth, uint16 newHeight) const { + +	Common::Rect srcRect(0, 0, (int16)w, (int16)h); +	Common::Rect dstRect(0, 0, (int16)newWidth, (int16)newHeight); + +	TransparentSurface *target = new TransparentSurface(); + +	assert(format.bytesPerPixel == 4); + +	int srcW = srcRect.width(); +	int srcH = srcRect.height(); +	int dstW = dstRect.width(); +	int dstH = dstRect.height(); + +	target->create((uint16)dstW, (uint16)dstH, this->format); + +#ifdef ENABLE_BILINEAR + +	// NB: The actual order of these bytes may not be correct, but +	// since all values are treated equal, that does not matter. +	struct tColorRGBA { byte r; byte g; byte b; byte a; }; + +	bool flipx = false, flipy = false; // TODO: See mirroring comment in RenderTicket ctor + + +	int *sax = new int[dstW + 1]; +	int *say = new int[dstH + 1]; +	assert(sax && say); + +	/* +	* Precalculate row increments +	*/ +	int spixelw = (srcW - 1); +	int spixelh = (srcH - 1); +	int sx = (int) (65536.0f * (float) spixelw / (float) (dstW - 1)); +	int sy = (int) (65536.0f * (float) spixelh / (float) (dstH - 1)); + +	/* Maximum scaled source size */ +	int ssx = (srcW << 16) - 1; +	int ssy = (srcH << 16) - 1; + +	/* Precalculate horizontal row increments */ +	int csx = 0; +	int *csax = sax; +	for (int x = 0; x <= dstW; x++) { +		*csax = csx; +		csax++; +		csx += sx; + +		/* Guard from overflows */ +		if (csx > ssx) { +			csx = ssx; +		} +	} + +	/* Precalculate vertical row increments */ +	int csy = 0; +	int *csay = say; +	for (int y = 0; y <= dstH; y++) { +		*csay = csy; +		csay++; +		csy += sy; + +		/* Guard from overflows */ +		if (csy > ssy) { +			csy = ssy; +		} +	} + +	const tColorRGBA *sp = (const tColorRGBA *) getBasePtr(0, 0); +	tColorRGBA *dp = (tColorRGBA *) target->getBasePtr(0, 0); +	int spixelgap = srcW; + +	if (flipx) { +		sp += spixelw; +	} +	if (flipy) { +		sp += spixelgap * spixelh; +	} + +	csay = say; +	for (int y = 0; y < dstH; y++) { +		const tColorRGBA *csp = sp; +		csax = sax; +		for (int x = 0; x < dstW; x++) { +			/* +			* Setup color source pointers +			*/ +			int ex = (*csax & 0xffff); +			int ey = (*csay & 0xffff); +			int cx = (*csax >> 16); +			int cy = (*csay >> 16); + +			const tColorRGBA *c00, *c01, *c10, *c11; +			c00 = sp; +			c01 = sp; +			c10 = sp; +			if (cy < spixelh) { +				if (flipy) { +					c10 -= spixelgap; +				} else { +					c10 += spixelgap; +				} +			} +			c11 = c10; +			if (cx < spixelw) { +				if (flipx) { +					c01--; +					c11--; +				} else { +					c01++; +					c11++; +				} +			} + +			/* +			* Draw and interpolate colors +			*/ +			int t1, t2; +			t1 = ((((c01->r - c00->r) * ex) >> 16) + c00->r) & 0xff; +			t2 = ((((c11->r - c10->r) * ex) >> 16) + c10->r) & 0xff; +			dp->r = (((t2 - t1) * ey) >> 16) + t1; +			t1 = ((((c01->g - c00->g) * ex) >> 16) + c00->g) & 0xff; +			t2 = ((((c11->g - c10->g) * ex) >> 16) + c10->g) & 0xff; +			dp->g = (((t2 - t1) * ey) >> 16) + t1; +			t1 = ((((c01->b - c00->b) * ex) >> 16) + c00->b) & 0xff; +			t2 = ((((c11->b - c10->b) * ex) >> 16) + c10->b) & 0xff; +			dp->b = (((t2 - t1) * ey) >> 16) + t1; +			t1 = ((((c01->a - c00->a) * ex) >> 16) + c00->a) & 0xff; +			t2 = ((((c11->a - c10->a) * ex) >> 16) + c10->a) & 0xff; +			dp->a = (((t2 - t1) * ey) >> 16) + t1; + +			/* +			* Advance source pointer x +			*/ +			int *salastx = csax; +			csax++; +			int sstepx = (*csax >> 16) - (*salastx >> 16); +			if (flipx) { +				sp -= sstepx; +			} else { +				sp += sstepx; +			} + +			/* +			* Advance destination pointer x +			*/ +			dp++; +		} +		/* +		* Advance source pointer y +		*/ +		int *salasty = csay; +		csay++; +		int sstepy = (*csay >> 16) - (*salasty >> 16); +		sstepy *= spixelgap; +		if (flipy) { +			sp = csp - sstepy; +		} else { +			sp = csp + sstepy; +		} +	} + +	delete[] sax; +	delete[] say; + +#else + +	int *scaleCacheX = new int[dstW]; +	for (int x = 0; x < dstW; x++) { +		scaleCacheX[x] = (x * srcW) / dstW; +	} + +	for (int y = 0; y < dstH; y++) { +		uint32 *destP = (uint32 *)target->getBasePtr(0, y); +		const uint32 *srcP = (const uint32 *)getBasePtr(0, (y * srcH) / dstH); +		for (int x = 0; x < dstW; x++) { +			*destP++ = srcP[scaleCacheX[x]]; +		} +	} +	delete[] scaleCacheX; + +#endif + +	return target; + +} + +} // End of namespace Graphics diff --git a/graphics/transparent_surface.h b/graphics/transparent_surface.h new file mode 100644 index 0000000000..cc35f8e6a0 --- /dev/null +++ b/graphics/transparent_surface.h @@ -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. + * + */ + +#ifndef GRAPHICS_TRANSPARENTSURFACE_H +#define GRAPHICS_TRANSPARENTSURFACE_H + +#include "graphics/surface.h" +#include "graphics/transform_struct.h" + +/* + * This code is based on Broken Sword 2.5 engine + * + * Copyright (c) Malte Thiesen, Daniel Queteschiner and Michael Elsdoerfer + * + * Licensed under GNU GPL v2 + * + */ + +// TODO: Find a better solution for this. +#define BS_RGB(R,G,B)       (0xFF000000 | ((R) << 16) | ((G) << 8) | (B)) +#define BS_ARGB(A,R,G,B)    (((A) << 24) | ((R) << 16) | ((G) << 8) | (B)) + +namespace Graphics { + +// Enums +/** + @brief The possible flipping parameters for the blit method. + */ +enum FLIP_FLAGS { +    /// The image will not be flipped. +    FLIP_NONE = 0, +    /// The image will be flipped at the horizontal axis. +    FLIP_H = 1, +    /// The image will be flipped at the vertical axis. +    FLIP_V = 2, +    /// The image will be flipped at the horizontal and vertical axis. +    FLIP_HV = FLIP_H | FLIP_V, +    /// The image will be flipped at the horizontal and vertical axis. +    FLIP_VH = FLIP_H | FLIP_V +}; + +enum AlphaType { +    ALPHA_OPAQUE = 0, +    ALPHA_BINARY = 1, +    ALPHA_FULL = 2 +}; + +/** + * A transparent graphics surface, which implements alpha blitting. + */ +struct TransparentSurface : public Graphics::Surface { +	TransparentSurface(); +	TransparentSurface(const Graphics::Surface &surf, bool copyData = false); + +	void setColorKey(char r, char g, char b); +	void disableColorKey(); + +	/** +	 @brief renders the surface to another surface +	 @param target a pointer to the target surface. In most cases this is the framebuffer. +	 @param posX the position on the X-axis in the target image in pixels where the image is supposed to be rendered.<br> +	 The default value is 0. +	 @param posY the position on the Y-axis in the target image in pixels where the image is supposed to be rendered.<br> +	 The default value is 0. +	 @param flipping how the the image should be flipped.<br> +	 The default value is BS_Image::FLIP_NONE (no flipping) +	 @param pPartRect Pointer on Common::Rect which specifies the section to be rendered. If the whole image has to be rendered the Pointer is NULL.<br> +	 This referes to the unflipped and unscaled image.<br> +	 The default value is NULL. +	 @param color an ARGB color value, which determines the parameters for the color modulation und alpha blending.<br> +	 The alpha component of the color determines the alpha blending parameter (0 = no covering, 255 = full covering).<br> +	 The color components determines the color for color modulation.<br> +	 The default value is BS_ARGB(255, 255, 255, 255) (full covering, no color modulation). +	 The macros BS_RGB and BS_ARGB can be used for the creation of the color value. +	 @param width the output width of the screen section. +	 The images will be scaled if the output width of the screen section differs from the image section.<br> +	 The value -1 determines that the image should not be scaled.<br> +	 The default value is -1. +	 @param height the output height of the screen section. +	 The images will be scaled if the output width of the screen section differs from the image section.<br> +	 The value -1 determines that the image should not be scaled.<br> +	 The default value is -1. +	 @return returns false if the rendering failed. +	 */ +	Common::Rect blit(Graphics::Surface &target, int posX = 0, int posY = 0, +	                  int flipping = FLIP_NONE, +	                  Common::Rect *pPartRect = nullptr, +	                  uint color = BS_ARGB(255, 255, 255, 255), +	                  int width = -1, int height = -1, +	                  TSpriteBlendMode blend = BLEND_NORMAL); +	void applyColorKey(uint8 r, uint8 g, uint8 b, bool overwriteAlpha = false); + +	/** +	 * @brief Scale function; this returns a transformed version of this surface after rotation and +	 * scaling. Please do not use this if angle != 0, use rotoscale. +	 * +	 * @param newWidth the resulting width. +	 * @param newHeight the resulting height. +	 * @see TransformStruct +	 */ +	TransparentSurface *scale(uint16 newWidth, uint16 newHeight) const; + +	/** +	 * @brief Rotoscale function; this returns a transformed version of this surface after rotation and +	 * scaling. Please do not use this if angle == 0, use plain old scaling function. +	 * +	 * @param transform a TransformStruct wrapping the required info. @see TransformStruct +	 * +	 */ +	TransparentSurface *rotoscale(const TransformStruct &transform) const; +	AlphaType getAlphaMode() const; +	void setAlphaMode(AlphaType); +private: +	AlphaType _alphaMode; + +}; + +/** + * A deleter for Surface objects which can be used with SharedPtr. + * + * This deleter assures Surface::free is called on deletion. + */ +/*struct SharedPtrTransparentSurfaceDeleter { +    void operator()(TransparentSurface *ptr) { +        ptr->free(); +        delete ptr; +    } +};*/ + +} // End of namespace Graphics + + +#endif  | 
