aboutsummaryrefslogtreecommitdiff
path: root/engines/wintermute
diff options
context:
space:
mode:
authorTobia Tesan2013-06-27 16:27:51 +0200
committerTobia Tesan2013-07-31 23:58:23 +0200
commit384dd8da7ef8cc7660607301c36b52645942faf0 (patch)
treec6068a38ff5217f8fb210a781cb6b7bb363d387d /engines/wintermute
parent66ba2ea4558bab4583a7d7bb27e1e254c34f579f (diff)
downloadscummvm-rg350-384dd8da7ef8cc7660607301c36b52645942faf0.tar.gz
scummvm-rg350-384dd8da7ef8cc7660607301c36b52645942faf0.tar.bz2
scummvm-rg350-384dd8da7ef8cc7660607301c36b52645942faf0.zip
WINTERMUTE: Bilinear scaling.
Refactor scale(), factor out actual mapping algorithm, add bilinear scaling
Diffstat (limited to 'engines/wintermute')
-rw-r--r--engines/wintermute/graphics/transparent_surface.cpp129
-rw-r--r--engines/wintermute/graphics/transparent_surface.h12
2 files changed, 128 insertions, 13 deletions
diff --git a/engines/wintermute/graphics/transparent_surface.cpp b/engines/wintermute/graphics/transparent_surface.cpp
index dcdcbf247e..f68259fb94 100644
--- a/engines/wintermute/graphics/transparent_surface.cpp
+++ b/engines/wintermute/graphics/transparent_surface.cpp
@@ -29,6 +29,117 @@
namespace Wintermute {
+void TransparentSurface::nearestCopy(float projX, float projY, int dstX, int dstY, const Common::Rect &srcRect, const Common::Rect &dstRect, const TransparentSurface *src, TransparentSurface *dst) {
+ int srcW = srcRect.width();
+ int srcH = srcRect.height();
+ int dstW = dstRect.width();
+ int dstH = dstRect.height();
+
+ assert(dstX >= 0 && dstX < dstW);
+ assert(dstY >= 0 && dstY < dstH);
+
+ uint32 color;
+
+ if (projX >= srcW || projX < 0 || projY >= srcH || projY < 0) {
+ color = 0;
+ } else {
+ color = READ_UINT32((const byte *)src->getBasePtr(projX, projY));
+ }
+
+ WRITE_UINT32((byte *)dst->getBasePtr(dstX, dstY), color);
+}
+
+void TransparentSurface::bilinearCopy(float projX, float projY, int dstX, int dstY, const Common::Rect &srcRect, const Common::Rect &dstRect, const TransparentSurface *src, TransparentSurface *dst) {
+
+ int srcW = srcRect.width();
+ int srcH = srcRect.height();
+ int dstW = dstRect.width();
+ int dstH = dstRect.height();
+
+ assert(dstX >= 0 && dstX < dstW);
+ assert(dstY >= 0 && dstY < dstH);
+
+ float x1 = floor(projX);
+ float x2 = ceil(projX);
+ float y1 = floor(projY);
+ float y2 = ceil(projY);
+
+ uint32 Q11, Q12, Q21, Q22;
+
+ if (x1 >= srcW || x1 < 0 || y1 >= srcH || y1 < 0) {
+ Q11 = 0;
+ } else {
+ Q11 = READ_UINT32((const byte *)src->getBasePtr(x1 + srcRect.left, y1 + srcRect.top));
+ }
+
+ if (x1 >= srcW || x1 < 0 || y2 >= srcH || y2 < 0) {
+ Q12 = 0;
+ } else {
+ Q12 = READ_UINT32((const byte *)src->getBasePtr(x1 + srcRect.left, y2 + srcRect.top));
+ }
+
+ if (x2 >= srcW || x2 < 0 || y1 >= srcH || y1 < 0) {
+ Q21 = 0;
+ } else {
+ Q21 = READ_UINT32((const byte *)src->getBasePtr(x2 + srcRect.left, y1 + srcRect.top));
+ }
+
+ if (x2 >= srcW || x2 < 0 || y2 >= srcH || y2 < 0) {
+ Q22 = 0;
+ } else {
+ Q22 = READ_UINT32((const byte *)src->getBasePtr(x2 + srcRect.left, y2 + srcRect.top));
+ }
+
+ byte *Q11s = (byte *)&Q11;
+ byte *Q12s = (byte *)&Q12;
+ byte *Q21s = (byte *)&Q21;
+ byte *Q22s = (byte *)&Q22;
+
+ uint32 color;
+ byte *dest = (byte *)&color;
+
+ float q11x = (x2 - projX);
+ float q11y = (y2 - projY);
+ float q21x = (projX - x1);
+ float q21y = (y2 - projY);
+ float q12x = (x2 - projX);
+ float q12y = (projY - y1);
+ float q22x = (projX - x1);
+ float q22y = (projY - y1);
+
+ if (x1 == x2 && y1 == y2) {
+ for (int c = 0; c < 4; c++) {
+ dest[c] = ((float)Q11s[c]);
+ }
+ } else {
+
+ if (x1 == x2) {
+ q11x = 0.5;
+ q12x = 0.5;
+ q21x = 0.5;
+ q22x = 0.5;
+ } else if (y1 == y2) {
+ q11y = 0.5;
+ q12y = 0.5;
+ q21y = 0.5;
+ q22y = 0.5;
+ }
+
+ for (int c = 0; c < 4; c++) {
+ dest[c] = (
+ ((float)Q11s[c]) * q11x * q11y +
+ ((float)Q21s[c]) * q21x * q21y +
+ ((float)Q12s[c]) * q12x * q12y +
+ ((float)Q22s[c]) * (1.0 -
+ q11x * q11y -
+ q21x * q21y -
+ q12x * q12y)
+ );
+ }
+ }
+ WRITE_UINT32((byte *)dst->getBasePtr(dstX + dstRect.left, dstY + dstRect.top), color);
+}
+
byte *TransparentSurface::_lookup = nullptr;
void TransparentSurface::destroyLookup() {
@@ -386,13 +497,7 @@ Common::Rect TransparentSurface::blit(Graphics::Surface &target, int posX, int p
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);
- return scale(srcRect, dstRect);
-}
-
-// Copied from clone2727's https://github.com/clone2727/scummvm/blob/pegasus/engines/pegasus/surface.cpp#L247
-TransparentSurface *TransparentSurface::scale(const Common::Rect &srcRect, const Common::Rect &dstRect) const {
- // I'm doing simple linear scaling here
- // dstRect(x, y) = srcRect(x * srcW / dstW, y * srcH / dstH);
+
TransparentSurface *target = new TransparentSurface();
assert(format.bytesPerPixel == 4);
@@ -406,9 +511,13 @@ TransparentSurface *TransparentSurface::scale(const Common::Rect &srcRect, const
for (int y = 0; y < dstH; y++) {
for (int x = 0; x < dstW; x++) {
- uint32 color = READ_UINT32((const byte *)getBasePtr(x * srcW / dstW + srcRect.left,
- y * srcH / dstH + srcRect.top));
- WRITE_UINT32((byte *)target->getBasePtr(x + dstRect.left, y + dstRect.top), color);
+ float projX = x / (float)dstW * srcW;
+ float projY = y / (float)dstH * srcH;
+ if (FAST_TRANSFORM) {
+ nearestCopy(projX, projY, x, y, srcRect, dstRect, this, target);
+ } else {
+ bilinearCopy(projX, projY, x, y, srcRect, dstRect, this, target);
+ }
}
}
return target;
diff --git a/engines/wintermute/graphics/transparent_surface.h b/engines/wintermute/graphics/transparent_surface.h
index dc079a1fbc..0f48054d7c 100644
--- a/engines/wintermute/graphics/transparent_surface.h
+++ b/engines/wintermute/graphics/transparent_surface.h
@@ -24,6 +24,10 @@
#include "graphics/surface.h"
+
+#define FAST_TRANSFORM 0
+
+
/*
* This code is based on Broken Sword 2.5 engine
*
@@ -49,6 +53,9 @@ struct TransparentSurface : public Graphics::Surface {
void setColorKey(char r, char g, char b);
void disableColorKey();
+ static void bilinearCopy(float projX, float projY, int dstX, int dstY, const Common::Rect &srcRect, const Common::Rect &dstRect, const TransparentSurface *src, TransparentSurface *dst);
+ static void nearestCopy(float projX, float projY, int dstX, int dstY, const Common::Rect &srcRect, const Common::Rect &dstRect, const TransparentSurface *src, TransparentSurface *dst);
+
// Enums
/**
@brief The possible flipping parameters for the blit methode.
@@ -102,9 +109,8 @@ struct TransparentSurface : public Graphics::Surface {
uint color = BS_ARGB(255, 255, 255, 255),
int width = -1, int height = -1);
void applyColorKey(uint8 r, uint8 g, uint8 b, bool overwriteAlpha = false);
- // The following scale-code supports arbitrary scaling (i.e. no repeats of column 0 at the end of lines)
- TransparentSurface *scale(uint16 newWidth, uint16 newHeight) const;
- TransparentSurface *scale(const Common::Rect &srcRect, const Common::Rect &dstRect) const;
+
+ TransparentSurface *scale (uint16 newWidth, uint16 newHeight) const;
static byte *_lookup;
static void destroyLookup();
private: