[Scummvm-git-logs] scummvm master -> 394288db981dbae6a983c14ad4dc7efcb9a8d659

bluegr bluegr at gmail.com
Mon Apr 19 00:08:14 UTC 2021


This automated email contains information about 1 new commit which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .

Summary:
394288db98 GRAPHICS: Move rotoscale code out of TransparentSurface


Commit: 394288db981dbae6a983c14ad4dc7efcb9a8d659
    https://github.com/scummvm/scummvm/commit/394288db981dbae6a983c14ad4dc7efcb9a8d659
Author: Cameron Cawley (ccawley2011 at gmail.com)
Date: 2021-04-19T03:08:11+03:00

Commit Message:
GRAPHICS: Move rotoscale code out of TransparentSurface

Changed paths:
    engines/wintermute/base/gfx/osystem/render_ticket.cpp
    graphics/conversion.cpp
    graphics/conversion.h
    graphics/surface.cpp
    graphics/surface.h
    graphics/transparent_surface.cpp
    graphics/transparent_surface.h


diff --git a/engines/wintermute/base/gfx/osystem/render_ticket.cpp b/engines/wintermute/base/gfx/osystem/render_ticket.cpp
index d5297d6529..a2ef4d3a49 100644
--- a/engines/wintermute/base/gfx/osystem/render_ticket.cpp
+++ b/engines/wintermute/base/gfx/osystem/render_ticket.cpp
@@ -59,13 +59,7 @@ RenderTicket::RenderTicket(BaseSurfaceOSystem *owner, const Graphics::Surface *s
 		// (Mirroring should most likely be done before rotation. See also
 		// TransformTools.)
 		if (_transform._angle != Graphics::kDefaultAngle) {
-			Graphics::TransparentSurface src(*_surface, false);
-			Graphics::Surface *temp;
-			if (owner->_gameRef->getBilinearFiltering()) {
-				temp = src.rotoscaleT<Graphics::FILTER_BILINEAR>(transform);
-			} else {
-				temp = src.rotoscaleT<Graphics::FILTER_NEAREST>(transform);
-			}
+			Graphics::Surface *temp = _surface->rotoscale(transform, owner->_gameRef->getBilinearFiltering());
 			_surface->free();
 			delete _surface;
 			_surface = temp;
diff --git a/graphics/conversion.cpp b/graphics/conversion.cpp
index edbe8df248..294a383e7c 100644
--- a/graphics/conversion.cpp
+++ b/graphics/conversion.cpp
@@ -18,12 +18,20 @@
  * 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 "graphics/conversion.h"
 #include "graphics/pixelformat.h"
+#include "graphics/transform_struct.h"
 
 #include "common/endian.h"
+#include "common/math.h"
+#include "common/rect.h"
 
 namespace Graphics {
 
@@ -437,6 +445,96 @@ void scaleBlitBilinearLogic(byte *dst, const byte *src,
 	}
 }
 
+template <typename Size, bool filtering, bool flipx, bool flipy> // TODO: See mirroring comment in RenderTicket ctor
+void rotoscaleBlitLogic(byte *dst, const byte *src,
+                       const uint dstPitch, const uint srcPitch,
+                       const uint dstW, const uint dstH,
+                       const uint srcW, const uint srcH,
+                       const Graphics::PixelFormat &fmt,
+                       const TransformStruct &transform,
+                       const Common::Point &newHotspot) {
+
+	assert(transform._angle != kDefaultAngle); // This would not be ideal; rotoscale() should never be called in conditional branches where angle = 0 anyway.
+
+	if (transform._zoom.x == 0 || transform._zoom.y == 0) {
+		return;
+	}
+
+	uint32 invAngle = 360 - (transform._angle % 360);
+	float invAngleRad = Common::deg2rad<uint32,float>(invAngle);
+	float invCos = cos(invAngleRad);
+	float invSin = sin(invAngleRad);
+
+	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));
+
+	int xd = transform._hotspot.x << 16;
+	int yd = 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;
+
+	Size *pc = (Size *)dst;
+
+	for (uint y = 0; y < dstH; y++) {
+		int t = cy - y;
+		int sdx = ax + (isinx * t) + xd;
+		int sdy = ay - (icosy * t) + yd;
+		for (uint x = 0; x < dstW; x++) {
+			int dx = (sdx >> 16);
+			int dy = (sdy >> 16);
+			if (flipx) {
+				dx = sw - dx;
+			}
+			if (flipy) {
+				dy = sh - dy;
+			}
+
+			if (filtering) {
+				if ((dx > -1) && (dy > -1) && (dx < sw) && (dy < sh)) {
+					const byte *sp = src + dy * srcPitch + dx * sizeof(Size);
+					Size c00, c01, c10, c11;
+					c00 = *(const Size *)sp;
+					sp += sizeof(Size);
+					c01 = *(const Size *)sp;
+					sp += srcPitch;
+					c11 = *(const Size *)sp;
+					sp -= sizeof(Size);
+					c10 = *(const Size *)sp;
+					if (flipx) {
+						SWAP(c00, c01);
+						SWAP(c10, c11);
+					}
+					if (flipy) {
+						SWAP(c00, c10);
+						SWAP(c01, c11);
+					}
+					/*
+					* Interpolate colors
+					*/
+					int ex = (sdx & 0xffff);
+					int ey = (sdy & 0xffff);
+					*pc = scaleBlitBilinearInterpolate(c01, c00, c11, c10, ex, ey, fmt);
+				}
+			} else {
+				if ((dx >= 0) && (dy >= 0) && (dx < (int)srcW) && (dy < (int)srcH)) {
+					const byte *sp = src + dy * srcPitch + dx * sizeof(Size);
+					*pc = *(const Size *)sp;
+				}
+			}
+			sdx += icosx;
+			sdy += isiny;
+			pc++;
+		}
+	}
+}
+
 } // End of anonymous namespace
 
 bool scaleBlitBilinear(byte *dst, const byte *src,
@@ -508,4 +606,42 @@ bool scaleBlitBilinear(byte *dst, const byte *src,
 	return true;
 }
 
+bool rotoscaleBlit(byte *dst, const byte *src,
+                   const uint dstPitch, const uint srcPitch,
+                   const uint dstW, const uint dstH,
+                   const uint srcW, const uint srcH,
+                   const Graphics::PixelFormat &fmt,
+                   const TransformStruct &transform,
+                   const Common::Point &newHotspot) {
+	if (fmt.bytesPerPixel == 4) {
+		rotoscaleBlitLogic<uint32, false, false, false>(dst, src, dstPitch, srcPitch, dstW, dstH, srcW, srcH, fmt, transform, newHotspot);
+	} else if (fmt.bytesPerPixel == 2) {
+		rotoscaleBlitLogic<uint16, false, false, false>(dst, src, dstPitch, srcPitch, dstW, dstH, srcW, srcH, fmt, transform, newHotspot);
+	} else if (fmt.bytesPerPixel == 1) {
+		rotoscaleBlitLogic<uint8, false, false, false>(dst, src, dstPitch, srcPitch, dstW, dstH, srcW, srcH, fmt, transform, newHotspot);
+	} else {
+		return false;
+	}
+
+	return true;
+}
+
+bool rotoscaleBlitBilinear(byte *dst, const byte *src,
+                           const uint dstPitch, const uint srcPitch,
+                           const uint dstW, const uint dstH,
+                           const uint srcW, const uint srcH,
+                           const Graphics::PixelFormat &fmt,
+                           const TransformStruct &transform,
+                           const Common::Point &newHotspot) {
+	if (fmt.bytesPerPixel == 4) {
+		rotoscaleBlitLogic<uint32, true, false, false>(dst, src, dstPitch, srcPitch, dstW, dstH, srcW, srcH, fmt, transform, newHotspot);
+	} else if (fmt.bytesPerPixel == 2) {
+		rotoscaleBlitLogic<uint16, true, false, false>(dst, src, dstPitch, srcPitch, dstW, dstH, srcW, srcH, fmt, transform, newHotspot);
+	} else {
+		return false;
+	}
+
+	return true;
+}
+
 } // End of namespace Graphics
diff --git a/graphics/conversion.h b/graphics/conversion.h
index 02d989495f..5ccb295959 100644
--- a/graphics/conversion.h
+++ b/graphics/conversion.h
@@ -25,6 +25,10 @@
 
 #include "common/util.h"
 
+namespace Common {
+struct Point;
+}
+
 namespace Graphics {
 
 /**
@@ -37,6 +41,7 @@ namespace Graphics {
  */
 
 struct PixelFormat;
+struct TransformStruct;
 
 /** Converting a color from YUV to RGB colorspace. */
 inline static void YUV2RGB(byte y, byte u, byte v, byte &r, byte &g, byte &b) {
@@ -124,6 +129,22 @@ bool scaleBlitBilinear(byte *dst, const byte *src,
 					   const uint dstW, const uint dstH,
 					   const uint srcW, const uint srcH,
 					   const Graphics::PixelFormat &fmt);
+
+bool rotoscaleBlit(byte *dst, const byte *src,
+                   const uint dstPitch, const uint srcPitch,
+                   const uint dstW, const uint dstH,
+                   const uint srcW, const uint srcH,
+                   const Graphics::PixelFormat &fmt,
+                   const TransformStruct &transform,
+                   const Common::Point &newHotspot);
+
+bool rotoscaleBlitBilinear(byte *dst, const byte *src,
+                           const uint dstPitch, const uint srcPitch,
+                           const uint dstW, const uint dstH,
+                           const uint srcW, const uint srcH,
+                           const Graphics::PixelFormat &fmt,
+                           const TransformStruct &transform,
+                           const Common::Point &newHotspot);
 /** @} */
 } // End of namespace Graphics
 
diff --git a/graphics/surface.cpp b/graphics/surface.cpp
index ebdf2256f8..2cd9343acd 100644
--- a/graphics/surface.cpp
+++ b/graphics/surface.cpp
@@ -28,6 +28,7 @@
 #include "graphics/primitives.h"
 #include "graphics/surface.h"
 #include "graphics/conversion.h"
+#include "graphics/transform_tools.h"
 
 namespace Graphics {
 
@@ -383,6 +384,24 @@ Graphics::Surface *Surface::scale(uint16 newWidth, uint16 newHeight, bool filter
 	return target;
 }
 
+Graphics::Surface *Surface::rotoscale(const TransformStruct &transform, bool filtering) const {
+
+	Common::Point newHotspot;
+	Common::Rect rect = TransformTools::newRect(Common::Rect((int16)w, (int16)h), transform, &newHotspot);
+
+	Graphics::Surface *target = new Graphics::Surface();
+
+	target->create((uint16)rect.right - rect.left, (uint16)rect.bottom - rect.top, this->format);
+
+	if (filtering) {
+		rotoscaleBlitBilinear((byte *)target->getPixels(), (const byte *)getPixels(), target->pitch, pitch, target->w, target->h, w, h, format, transform, newHotspot);
+	} else {
+		rotoscaleBlit((byte *)target->getPixels(), (const byte *)getPixels(), target->pitch, pitch, target->w, target->h, w, h, format, transform, newHotspot);
+	}
+
+	return target;
+}
+
 void Surface::convertToInPlace(const PixelFormat &dstFormat, const byte *palette) {
 	// Do not convert to the same format and ignore empty surfaces.
 	if (format == dstFormat || pixels == 0) {
diff --git a/graphics/surface.h b/graphics/surface.h
index 6aa7a7b422..152bc0ff1c 100644
--- a/graphics/surface.h
+++ b/graphics/surface.h
@@ -45,6 +45,8 @@ namespace Graphics {
  * @{
  */
 
+struct TransformStruct;
+
 /**
  * An arbitrary graphics surface that can be the target (or source) of blit
  * operations, font rendering, etc.
@@ -409,6 +411,19 @@ public:
 	 */
 	Graphics::Surface *scale(uint16 newWidth, uint16 newHeight, bool filtering = false) 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.
+	 *
+	 * The client code must call @ref free on the returned surface and then delete
+	 * it.
+	 *
+	 * @param transform a TransformStruct wrapping the required info. @see TransformStruct
+	 * @param filtering Whether or not to use bilinear filtering.
+	 *
+	 */
+	Graphics::Surface *rotoscale(const TransformStruct &transform, bool filtering = false) const;
+
 };
 
 /**
diff --git a/graphics/transparent_surface.cpp b/graphics/transparent_surface.cpp
index 21dd893b47..a1b03bd340 100644
--- a/graphics/transparent_surface.cpp
+++ b/graphics/transparent_surface.cpp
@@ -18,11 +18,6 @@
  * 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.
- *
  */
 
 
@@ -744,181 +739,34 @@ void TransparentSurface::setAlphaMode(AlphaType mode) {
 	_alphaMode = mode;
 }
 
-
-
-
-
-
-/*
-
-The function below is 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.
-
-*/
-
-
-
-
-struct tColorRGBA { byte r; byte g; byte b; byte a; };
-
-template <TFilteringMode filteringMode>
-TransparentSurface *TransparentSurface::rotoscaleT(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 *TransparentSurface::scale(uint16 newWidth, uint16 newHeight, bool filtering) const {
 
 	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);
+	target->create(newWidth, newHeight, format);
 
-	if (transform._zoom.x == 0 || transform._zoom.y == 0) {
-		return target;
+	if (filtering) {
+		scaleBlitBilinear((byte *)target->getPixels(), (const byte *)getPixels(), target->pitch, pitch, target->w, target->h, w, h, format);
+	} else {
+		scaleBlit((byte *)target->getPixels(), (const byte *)getPixels(), target->pitch, pitch, target->w, target->h, w, h, format);
 	}
 
-	uint32 invAngle = 360 - (transform._angle % 360);
-	float invAngleRad = Common::deg2rad<uint32,float>(invAngle);
-	float invCos = cos(invAngleRad);
-	float invSin = sin(invAngleRad);
-
-	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;
-			}
-
-			if (filteringMode == FILTER_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;
-				}
-			}
-			sdx += icosx;
-			sdy += isiny;
-			pc++;
-		}
-	}
 	return target;
 }
 
-TransparentSurface *TransparentSurface::scale(uint16 newWidth, uint16 newHeight, bool filtering) const {
+TransparentSurface *TransparentSurface::rotoscale(const TransformStruct &transform, bool filtering) const {
+
+	Common::Point newHotspot;
+	Common::Rect rect = TransformTools::newRect(Common::Rect((int16)w, (int16)h), transform, &newHotspot);
 
 	TransparentSurface *target = new TransparentSurface();
 
-	target->create(newWidth, newHeight, format);
+	target->create((uint16)rect.right - rect.left, (uint16)rect.bottom - rect.top, this->format);
 
 	if (filtering) {
-		scaleBlitBilinear((byte *)target->getPixels(), (const byte *)getPixels(), target->pitch, pitch, target->w, target->h, w, h, format);
+		rotoscaleBlitBilinear((byte *)target->getPixels(), (const byte *)getPixels(), target->pitch, pitch, target->w, target->h, w, h, format, transform, newHotspot);
 	} else {
-		scaleBlit((byte *)target->getPixels(), (const byte *)getPixels(), target->pitch, pitch, target->w, target->h, w, h, format);
+		rotoscaleBlit((byte *)target->getPixels(), (const byte *)getPixels(), target->pitch, pitch, target->w, target->h, w, h, format, transform, newHotspot);
 	}
 
 	return target;
@@ -1002,11 +850,4 @@ TransparentSurface *TransparentSurface::convertTo(const PixelFormat &dstFormat,
 	return surface;
 }
 
-template TransparentSurface *TransparentSurface::rotoscaleT<FILTER_NEAREST>(const TransformStruct &transform) const;
-template TransparentSurface *TransparentSurface::rotoscaleT<FILTER_BILINEAR>(const TransformStruct &transform) const;
-
-TransparentSurface *TransparentSurface::rotoscale(const TransformStruct &transform) const {
-	return rotoscaleT<FILTER_BILINEAR>(transform);
-}
-
 } // End of namespace Graphics
diff --git a/graphics/transparent_surface.h b/graphics/transparent_surface.h
index 8277eefd73..c23a33368f 100644
--- a/graphics/transparent_surface.h
+++ b/graphics/transparent_surface.h
@@ -77,11 +77,6 @@ enum AlphaType {
 	ALPHA_FULL = 2
 };
 
-enum TFilteringMode {
-	FILTER_NEAREST = 0,
-	FILTER_BILINEAR = 1
-};
-
 /**
  * A transparent graphics surface, which implements alpha blitting.
  */
@@ -161,12 +156,10 @@ struct TransparentSurface : public Graphics::Surface {
 	 * scaling. Please do not use this if angle == 0, use plain old scaling function.
 	 *
 	 * @param transform a TransformStruct wrapping the required info. @see TransformStruct
+	 * @param filtering Whether or not to use bilinear filtering.
 	 *
 	 */
-	template <TFilteringMode filteringMode>
-	TransparentSurface *rotoscaleT(const TransformStruct &transform) const;
-
-	TransparentSurface *rotoscale(const TransformStruct &transform) const;
+	TransparentSurface *rotoscale(const TransformStruct &transform, bool filtering = false) const;
 
 	TransparentSurface *convertTo(const PixelFormat &dstFormat, const byte *palette = 0) const;
 




More information about the Scummvm-git-logs mailing list