diff options
Diffstat (limited to 'engines/wintermute/graphics/transparent_surface.cpp')
| -rw-r--r-- | engines/wintermute/graphics/transparent_surface.cpp | 950 | 
1 files changed, 0 insertions, 950 deletions
diff --git a/engines/wintermute/graphics/transparent_surface.cpp b/engines/wintermute/graphics/transparent_surface.cpp deleted file mode 100644 index 5fe0d13766..0000000000 --- a/engines/wintermute/graphics/transparent_surface.cpp +++ /dev/null @@ -1,950 +0,0 @@ -/* 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 "engines/wintermute/graphics/transparent_surface.h" -#include "engines/wintermute/graphics/transform_tools.h" - -//#define ENABLE_BILINEAR - -namespace Wintermute { - -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); - -// These gather together various blendPixel functions for use with templates. - -class BlenderAdditive { -public: -	inline void blendPixel(byte ina, byte inr, byte ing, byte inb, byte *outa, byte *outr, byte *outg, byte *outb); -	inline void blendPixel(byte ina, byte inr, byte ing, byte inb, byte *outa, byte *outr, byte *outg, byte *outb, byte *ca, byte *cr, byte *cg, byte *cb); -	inline void blendPixel(byte *in, byte *out); -	inline void blendPixel(byte *in, byte *out, int colorMod); -}; - -class BlenderSubtractive { -public: -	inline void blendPixel(byte ina, byte inr, byte ing, byte inb, byte *outa, byte *outr, byte *outg, byte *outb); -	inline void blendPixel(byte ina, byte inr, byte ing, byte inb, byte *outa, byte *outr, byte *outg, byte *outb, byte *ca, byte *cr, byte *cg, byte *cb); -	inline void blendPixel(byte *in, byte *out); -	inline void blendPixel(byte *in, byte *out, int colorMod); -}; - -class BlenderNormal { -public: -	inline void blendPixel(byte ina, byte inr, byte ing, byte inb, byte *outa, byte *outr, byte *outg, byte *outb); -	inline void blendPixel(byte ina, byte inr, byte ing, byte inb, byte *outa, byte *outr, byte *outg, byte *outb, byte *ca, byte *cr, byte *cg, byte *cb); -	inline void blendPixel(byte *in, byte *out); -	inline void blendPixel(byte *in, byte *out, int colorMod); -}; - -/** - * Perform additive blending of a pixel, applying beforehand a given colormod. - * @param ina, inr, ing, inb: the input pixel, split into its components. - * @param *outa, *outr, *outg, *outb pointer to the output pixel. - * @param *outa, *outr, *outg, *outb pointer to the colormod components. - */ -void BlenderAdditive::blendPixel(byte ina, byte inr, byte ing, byte inb, byte *outa, byte *outr, byte *outg, byte *outb, byte *ca, byte *cr, byte *cg, byte *cb) { -	if (*ca != 255) { -		ina = (ina) * (*ca) >> 8; -	} - -	if (ina == 0) { -		return; -	} else { -		if (*cb != 255) { -			*outb = MIN(*outb + ((inb * (*cb) * ina) >> 16), 255); -		} else { -			*outb = MIN(*outb + (inb * ina >> 8), 255); -		} - -		if (*cg != 255) { -			*outg = MIN(*outg + ((ing * (*cg) * ina) >> 16), 255); -		} else { -			*outg = MIN(*outg + (ing * ina >> 8), 255); -		} - -		if (*cr != 255) { -			*outr = MIN(*outr + ((inr * (*cr) * ina) >> 16), 255); -		} else { -			*outr = MIN(*outr + (inr * ina >> 8), 255); -		} -	} -} - -/** - * Perform subtractive blending of a pixel, applying beforehand a given colormod. - * @param ina, inr, ing, inb: the input pixel, split into its components. - * @param *outa, *outr, *outg, *outb pointer to the output pixel. - * @param *outa, *outr, *outg, *outb pointer to the colormod components. - */ -void BlenderSubtractive::blendPixel(byte ina, byte inr, byte ing, byte inb, byte *outa, byte *outr, byte *outg, byte *outb, byte *ca, byte *cr, byte *cg, byte *cb) { -	//if (*ca != 255) { -	//	ina = ina * (*ca) >> 8; -	// } - -	// As weird as it is, evidence suggests that alphamod is ignored when doing -	// subtractive... - -	// TODO if ina == 255 fast version - -	if (ina == 0) { -		return; -	} else { -		if (*cb != 255) { -			*outb = MAX(*outb - ((inb * (*cb)  * (*outb) * ina) >> 24), 0); -		} else { -			*outb = MAX(*outb - (inb * (*outb) * ina >> 16), 0); -		} - -		if (*cg != 255) { -			*outg = MAX(*outg - ((ing * (*cg)  * (*outg) * ina) >> 24), 0); -		} else { -			*outg = MAX(*outg - (ing * (*outg) * ina >> 16), 0); -		} - -		if (*cr != 255) { -			*outr = MAX(*outr - ((inr * (*cr) * (*outr) * ina) >> 24), 0); -		} else { -			*outr = MAX(*outr - (inr * (*outr) * ina >> 16), 0); -		} -	} -} - -/** - * Perform "regular" alphablending of a pixel, applying beforehand a given colormod. - * @param ina, inr, ing, inb: the input pixel, split into its components. - * @param *outa, *outr, *outg, *outb pointer to the output pixel. - * @param *outa, *outr, *outg, *outb pointer to the colormod components. - */ - -void BlenderNormal::blendPixel(byte ina, byte inr, byte ing, byte inb, byte *outa, byte *outr, byte *outg, byte *outb, byte *ca, byte *cr, byte *cg, byte *cb) { -	if (*ca != 255) { -		ina = ina * (*ca) >> 8; -	} - -	if (ina == 0) { -		return; -	} else if (ina == 255) { -		if (*cb != 255) { -			*outb = (inb * (*cb)) >> 8; -		} else { -			*outb = inb; -		} - -		if (*cr != 255) { -			*outr = (inr * (*cr)) >> 8; -		} else { -			*outr = inr; -		} - -		if (*cg != 255) { -			*outg = (ing * (*cg)) >> 8; -		} else { -			*outg = ing; -		} - -		*outa = ina; - -		return; - -	} else { - -		*outa = 255; -		*outb = (*outb * (255 - ina) >> 8); -		*outr = (*outr * (255 - ina) >> 8); -		*outg = (*outg * (255 - ina) >> 8); - -		if (*cb == 0) { -			*outb = *outb; -		} else if (*cb != 255) { -			*outb = *outb + (inb * ina * (*cb) >> 16); -		} else { -			*outb = *outb + (inb * ina >> 8); -		} - -		if (*cr == 0) { -			*outr = *outr; -		} else if (*cr != 255) { -			*outr = *outr + (inr * ina * (*cr) >> 16); -		} else { -			*outr = *outr + (inr * ina >> 8); -		} - -		if (*cg == 0) { -			*outg = *outg; -		} else if (*cg != 255) { -			*outg = *outg + (ing * ina * (*cg) >> 16); -		} else { -			*outg = *outg + (ing * ina >> 8); -		} - -		return; -	} -} - -/** - * Perform "regular" alphablending of a pixel. - * @param ina, inr, ing, inb: the input pixel, split into its components. - * @param *outa, *outr, *outg, *outb pointer to the output pixel. - */ - -void BlenderNormal::blendPixel(byte ina, byte inr, byte ing, byte inb, byte *outa, byte *outr, byte *outg, byte *outb) { - -	if (ina == 0) { -		return; -	} else if (ina == 255) { -		*outb = inb; -		*outg = ing; -		*outr = inr; -		*outa = ina; -		return; -	} else { -		*outa = 255; -		*outb = ((inb * ina) + *outb * (255 - ina)) >> 8; -		*outg = ((ing * ina) + *outg * (255 - ina)) >> 8; -		*outr = ((inr * ina) + *outr * (255 - ina)) >> 8; -	} -} - -/** - * Perform subtractive blending of a pixel. - * @param ina, inr, ing, inb: the input pixel, split into its components. - * @param *outa, *outr, *outg, *outb pointer to the output pixel. - */ -void BlenderSubtractive::blendPixel(byte ina, byte inr, byte ing, byte inb, byte *outa, byte *outr, byte *outg, byte *outb) { - -	if (ina == 0) { -		return; -	} else if (ina == 255) { -		*outa = *outa; -		*outr = *outr - (inr * (*outr) >> 8); -		*outg = *outg - (ing * (*outg) >> 8); -		*outb = *outb - (inb * (*outb) >> 8); -		return; -	} else { -		*outa = *outa; -		*outb = MAX(*outb - ((inb * (*outb)) * ina >> 16), 0); -		*outg = MAX(*outg - ((ing * (*outg)) * ina >> 16), 0); -		*outr = MAX(*outr - ((inr * (*outr)) * ina >> 16), 0); -		return; -	} -} - -/** - * Perform additive blending of a pixel. - * @param ina, inr, ing, inb: the input pixel, split into its components. - * @param *outa, *outr, *outg, *outb pointer to the output pixel. - */ -void BlenderAdditive::blendPixel(byte ina, byte inr, byte ing, byte inb, byte *outa, byte *outr, byte *outg, byte *outb) { - -	if (ina == 0) { -		return; -	} else if (ina == 255) { -		*outa = *outa; -		*outr = MIN(*outr + inr, 255); -		*outg = MIN(*outg + ing, 255); -		*outb = MIN(*outb + inb, 255); -		return; -	} else { -		*outa = *outa; -		*outb = MIN((inb * ina >> 8) + *outb, 255); -		*outg = MIN((ing * ina >> 8) + *outg, 255); -		*outr = MIN((inr * ina >> 8) + *outr, 255); -		return; -	} -} - - -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[TransparentSurface::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 >> TransparentSurface::kAShift) & 0xff; - -			if (a == 0) { // Full transparency -			} else { // Full opacity (Any value not exactly 0 is Opaque here) -				*(uint32 *)out = pix; -				out[TransparentSurface::kAIndex] = 0xFF; -			} -			out += 4; -			in += inStep; -		} -		outo += pitch; -		ino += inoStep; -	} -} - -/** - * What we have here is a template method that calls blendPixel() from a different - * class - the one we call it with - thus performing a different type of blending. - * - * @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 - */ - -template<class Blender> -void doBlit(byte *ino, byte *outo, uint32 width, uint32 height, uint32 pitch, int32 inStep, int32 inoStep, uint32 color) { -	Blender b; -	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++) { - -				byte *outa = &out[TransparentSurface::kAIndex]; -				byte *outr = &out[TransparentSurface::kRIndex]; -				byte *outg = &out[TransparentSurface::kGIndex]; -				byte *outb = &out[TransparentSurface::kBIndex]; - -				b.blendPixel(in[TransparentSurface::kAIndex], -							 in[TransparentSurface::kRIndex], -							 in[TransparentSurface::kGIndex], -							 in[TransparentSurface::kBIndex], -							 outa, outr, outg, outb); - -				in += inStep; -				out += 4; -			} -			outo += pitch; -			ino += inoStep; -		} -	} else { - -		byte ca = (color >> TransparentSurface::kAModShift) & 0xFF; -		byte cr = (color >> TransparentSurface::kRModShift) & 0xFF; -		byte cg = (color >> TransparentSurface::kGModShift) & 0xFF; -		byte cb = (color >> TransparentSurface::kBModShift) & 0xFF; - -		for (uint32 i = 0; i < height; i++) { -			out = outo; -			in = ino; -			for (uint32 j = 0; j < width; j++) { - -				byte *outa = &out[TransparentSurface::kAIndex]; -				byte *outr = &out[TransparentSurface::kRIndex]; -				byte *outg = &out[TransparentSurface::kGIndex]; -				byte *outb = &out[TransparentSurface::kBIndex]; - -				b.blendPixel(in[TransparentSurface::kAIndex], -							 in[TransparentSurface::kRIndex], -							 in[TransparentSurface::kGIndex], -							 in[TransparentSurface::kBIndex], -							 outa, outr, outg, outb, &ca, &cr, &cg, &cb); -				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 32 bpp images"); -		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 & TransparentSurface::FLIP_H) { -			inStep = -inStep; -			xp = img->w - 1; -		} - -		if (flipping & TransparentSurface::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) { -				doBlit<BlenderAdditive>(ino, outo, img->w, img->h, target.pitch, inStep, inoStep, color); -			} else if (blendMode == BLEND_SUBTRACTIVE) { -				doBlit<BlenderSubtractive>(ino, outo, img->w, img->h, target.pitch, inStep, inoStep, color); -			} else { -				assert(blendMode == BLEND_NORMAL); -				doBlit<BlenderNormal>(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); -			} -		} -	} -} - -TransparentSurface::AlphaType TransparentSurface::getAlphaMode() const { -	return _alphaMode; -} - -void TransparentSurface::setAlphaMode(TransparentSurface::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. - -	Point32 newHotspot; -	Common::Rect srcRect(0, 0, (int16)w, (int16)h); -	Rect32 rect = TransformTools::newRect(Rect32(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 Wintermute  | 
