[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