aboutsummaryrefslogtreecommitdiff
path: root/sword2
diff options
context:
space:
mode:
authorTorbjörn Andersson2004-06-06 15:40:31 +0000
committerTorbjörn Andersson2004-06-06 15:40:31 +0000
commitc9c56d2f7242b02e9b23217dfcd1c657f9811ea0 (patch)
tree5b8fc93094be9de66d583a7aaa487b967e608037 /sword2
parent29f03f0d9c09572d8b37d3efc1cf34be7f149d16 (diff)
downloadscummvm-rg350-c9c56d2f7242b02e9b23217dfcd1c657f9811ea0.tar.gz
scummvm-rg350-c9c56d2f7242b02e9b23217dfcd1c657f9811ea0.tar.bz2
scummvm-rg350-c9c56d2f7242b02e9b23217dfcd1c657f9811ea0.zip
Cleaned up sprite scaling.
svn-id: r13944
Diffstat (limited to 'sword2')
-rw-r--r--sword2/driver/d_draw.h6
-rw-r--r--sword2/driver/menu.cpp4
-rw-r--r--sword2/driver/render.cpp316
-rw-r--r--sword2/driver/sprite.cpp24
4 files changed, 99 insertions, 251 deletions
diff --git a/sword2/driver/d_draw.h b/sword2/driver/d_draw.h
index 1177b3e6b7..2d8eb83412 100644
--- a/sword2/driver/d_draw.h
+++ b/sword2/driver/d_draw.h
@@ -153,10 +153,10 @@ private:
uint8 getMatch(uint8 r, uint8 g, uint8 b);
void fadeServer(void);
- void squashImage(byte *dst, uint16 dstPitch, uint16 dstWidth,
+ void scaleImageFast(byte *dst, uint16 dstPitch, uint16 dstWidth,
uint16 dstHeight, byte *src, uint16 srcPitch, uint16 srcWidth,
- uint16 srcHeight, byte *backbuf);
- void stretchImage(byte *dst, uint16 dstPitch, uint16 dstWidth,
+ uint16 srcHeight);
+ void scaleImageGood(byte *dst, uint16 dstPitch, uint16 dstWidth,
uint16 dstHeight, byte *src, uint16 srcPitch, uint16 srcWidth,
uint16 srcHeight, byte *backbuf);
diff --git a/sword2/driver/menu.cpp b/sword2/driver/menu.cpp
index 28ab6b955e..8fa68791db 100644
--- a/sword2/driver/menu.cpp
+++ b/sword2/driver/menu.cpp
@@ -156,9 +156,9 @@ void Graphics::processMenu(void) {
byte *src = _icons[menu][i];
if (_pocketStatus[menu][i] != MAXMENUANIMS) {
- squashImage(
+ scaleImageFast(
dst, _screenWide, r2.right - r2.left, r2.bottom - r2.top,
- src, RDMENU_ICONWIDE, RDMENU_ICONWIDE, RDMENU_ICONDEEP, NULL);
+ src, RDMENU_ICONWIDE, RDMENU_ICONWIDE, RDMENU_ICONDEEP);
} else {
for (j = 0; j < RDMENU_ICONDEEP; j++) {
memcpy(dst, src, RDMENU_ICONWIDE);
diff --git a/sword2/driver/render.cpp b/sword2/driver/render.cpp
index e76bdf7369..c6e9f745b2 100644
--- a/sword2/driver/render.cpp
+++ b/sword2/driver/render.cpp
@@ -77,249 +77,113 @@ void Graphics::blitBlockSurface(BlockSurface *s, Common::Rect *r, Common::Rect *
}
}
-// I've made the scaling two separate functions because there were cases from
-// DrawSprite() where it wasn't obvious if the sprite should grow or shrink,
-// which caused crashes.
+// There are two different separate functions for scaling the image - one fast
+// and one good. Or at least that's the theory. I'm sure there are better ways
+// to scale an image than this. The latter is used at the highest graphics
+// quality setting. Note that the "good" scaler takes an extra parameter, a
+// pointer to the area of the screen where the sprite will be drawn.
//
-// Keeping them separate might be a good idea anyway, for readability.
-//
-// The code is based on the original DrawSprite() code, so apart from not
-// knowing if I got it right, I don't know how good the original really is.
-//
-// The backbuf parameter points to the buffer where the image will eventually
-// be drawn. This is only used at the highest graphics detail setting (and not
-// always even then) and is used to help anti-alias the image.
-
-void Graphics::squashImage(byte *dst, uint16 dstPitch, uint16 dstWidth, uint16 dstHeight, byte *src, uint16 srcPitch, uint16 srcWidth, uint16 srcHeight, byte *backbuf) {
- int32 ince, incne, d;
- int16 x, y;
+// This code isn't quite like the original DrawSprite(), but should be close
+// enough.
- // Work out the x-scale
-
- ince = 2 * dstWidth;
- incne = 2 * (dstWidth - srcWidth);
- d = 2 * dstWidth - srcWidth;
- x = y = 0;
- _xScale[y] = x;
-
- while (x < srcWidth) {
- if (d <= 0) {
- d += ince;
- x++;
- } else {
- d += incne;
- x++;
- y++;
- }
- _xScale[y] = x;
- }
+void Graphics::scaleImageFast(byte *dst, uint16 dstPitch, uint16 dstWidth, uint16 dstHeight, byte *src, uint16 srcPitch, uint16 srcWidth, uint16 srcHeight) {
+ int x, y;
- // Work out the y-scale
+ for (x = 0; x < dstWidth; x++)
+ _xScale[x] = (x * srcWidth) / dstWidth;
- ince = 2 * dstHeight;
- incne = 2 * (dstHeight - srcHeight);
- d = 2 * dstHeight - srcHeight;
- x = y = 0;
- _yScale[y] = x;
+ for (y = 0; y < dstHeight; y++)
+ _yScale[y] = (y * srcHeight) / dstHeight;
- while (x < srcHeight) {
- if (d <= 0) {
- d += ince;
- x++;
- } else {
- d += incne;
- x++;
- y++;
- }
- _yScale[y] = x;
- }
-
- // Copy the image (with or without anti-aliasing)
-
- if (backbuf) {
- for (y = 0; y < dstHeight; y++) {
- for (x = 0; x < dstWidth; x++) {
- uint8 p;
- uint8 p1 = 0;
- int count = 0;
- int spriteCount = 0;
- int red = 0;
- int green = 0;
- int blue = 0;
- int i, j;
-
- for (j = _yScale[y]; j < _yScale[y + 1]; j++) {
- for (i = _xScale[x]; i < _xScale[x + 1]; i++) {
- p = src[j * srcPitch + i];
- if (p) {
- red += _palCopy[p][0];
- green += _palCopy[p][1];
- blue += _palCopy[p][2];
- p1 = p;
- spriteCount++;
- } else {
- red += _palCopy[backbuf[x]][0];
- green += _palCopy[backbuf[x]][1];
- blue += _palCopy[backbuf[x]][2];
- }
- count++;
- }
- }
- if (spriteCount == 0)
- dst[x] = 0;
- else if (spriteCount == 1)
- dst[x] = p1;
- else
- dst[x] = quickMatch((uint8) (red / count), (uint8) (green / count), (uint8) (blue / count));
- }
- dst += dstPitch;
- backbuf += _screenWide;
- }
- } else {
- for (y = 0; y < dstHeight; y++) {
- for (x = 0; x < dstWidth; x++) {
- dst[x] = src[_yScale[y] * srcPitch + _xScale[x]];
- }
- dst += dstPitch;
+ for (y = 0; y < dstHeight; y++) {
+ for (x = 0; x < dstWidth; x++) {
+ dst[x] = src[_yScale[y] * srcPitch + _xScale[x]];
}
+ dst += dstPitch;
}
}
-void Graphics::stretchImage(byte *dst, uint16 dstPitch, uint16 dstWidth, uint16 dstHeight, byte *src, uint16 srcPitch, uint16 srcWidth, uint16 srcHeight, byte *backbuf) {
- byte *origDst = dst;
- int32 ince, incne, d;
- int16 x, y, i, j, k;
-
- // Work out the x-scale
-
- ince = 2 * srcWidth;
- incne = 2 * (srcWidth - dstWidth);
- d = 2 * srcWidth - dstWidth;
- x = y = 0;
- _xScale[y] = x;
-
- while (x < dstWidth) {
- if (d <= 0) {
- d += ince;
- x++;
- } else {
- d += incne;
- x++;
- y++;
- _xScale[y] = x;
- }
- }
-
- // Work out the y-scale
-
- ince = 2 * srcHeight;
- incne = 2 * (srcHeight - dstHeight);
- d = 2 * srcHeight - dstHeight;
- x = y = 0;
- _yScale[y] = x;
- while (x < dstHeight) {
- if (d <= 0) {
- d += ince;
- x++;
- } else {
- d += incne;
- x++;
- y++;
- _yScale[y] = x;
- }
- }
+void Graphics::scaleImageGood(byte *dst, uint16 dstPitch, uint16 dstWidth, uint16 dstHeight, byte *src, uint16 srcPitch, uint16 srcWidth, uint16 srcHeight, byte *backbuf) {
+ for (int y = 0; y < dstHeight; y++) {
+ for (int x = 0; x < dstWidth; x++) {
+ uint8 c1, c2, c3, c4;
- // Copy the image
+ uint32 xPos = (x * srcWidth) / dstWidth;
+ uint32 yPos = (y * srcHeight) / dstHeight;
+ uint32 xFrac = dstWidth - (x * srcWidth) % dstWidth;
+ uint32 yFrac = dstHeight - (y * srcHeight) % dstHeight;
- for (y = 0; y < srcHeight; y++) {
- for (j = _yScale[y]; j < _yScale[y + 1]; j++) {
- k = 0;
- for (x = 0; x < srcWidth; x++) {
- for (i = _xScale[x]; i < _xScale[x + 1]; i++) {
- dst[k++] = src[y * srcPitch + x];
- }
- }
- dst += dstPitch;
- }
- }
-
- // Anti-aliasing
+ byte *srcPtr = src + yPos * srcPitch + xPos;
+ byte *backPtr = backbuf + y * _screenWide + x;
- if (backbuf) {
- byte *newDst = (byte *) malloc(dstWidth * dstHeight);
- if (!newDst)
- return;
+ bool transparent = true;
- memcpy(newDst, origDst, dstWidth);
+ if (*srcPtr) {
+ c1 = *srcPtr;
+ transparent = false;
+ } else
+ c1 = *backPtr;
- for (y = 1; y < dstHeight - 1; y++) {
- src = origDst + y * dstPitch;
- dst = newDst + y * dstWidth;
- *dst++ = *src++;
- for (x = 1; x < dstWidth - 1; x++) {
- byte pt[5];
- byte *p = backbuf + y * 640 + x;
- int count = 0;
-
- if (*src) {
- count++;
- pt[0] = *src;
+ if (x < dstWidth - 1) {
+ if (*(srcPtr + 1)) {
+ c2 = *(srcPtr + 1);
+ transparent = false;
} else
- pt[0] = *p;
-
- pt[1] = *(src - dstPitch);
- if (pt[1] == 0)
- pt[1] = *(p - 640);
- else
- count++;
-
- pt[2] = *(src - 1);
- if (pt[2] == 0)
- pt[2] = *(p - 1);
- else
- count++;
-
- pt[3] = *(src + 1);
- if (pt[3] == 0)
- pt[3] = *(p + 1);
- else
- count++;
-
- pt[4] = *(src + dstPitch);
- if (pt[4] == 0)
- pt[4] = *(p + 640);
- else
- count++;
-
- if (count) {
- int red = _palCopy[pt[0]][0] << 2;
- int green = _palCopy[pt[0]][1] << 2;
- int blue = _palCopy[pt[0]][2] << 2;
- for (i = 1; i < 5; i++) {
- red += _palCopy[pt[i]][0];
- green += _palCopy[pt[i]][1];
- blue += _palCopy[pt[i]][2];
- }
-
- *dst++ = quickMatch((uint8) (red >> 3), (uint8) (green >> 3), (uint8) (blue >> 3));
+ c2 = *(backPtr + 1);
+ } else
+ c2 = c1;
+
+ if (y < dstHeight - 1) {
+ if (*(srcPtr + srcPitch)) {
+ c3 = *(srcPtr + srcPitch);
+ transparent = false;
} else
- *dst++ = 0;
- src++;
- }
- *dst++ = *src++;
- }
- memcpy(dst, src, dstWidth);
-
- src = newDst;
- dst = origDst;
-
- for (i = 0; i < dstHeight; i++) {
- memcpy(dst, src, dstWidth);
- dst += dstPitch;
- src += dstWidth;
+ c3 = *(backPtr + _screenWide);
+ } else
+ c3 = c1;
+
+ if (x < dstWidth - 1 && y < dstHeight - 1) {
+ if (*(srcPtr + srcPitch + 1)) {
+ c4 = *(srcPtr + srcPitch + 1);
+ transparent = false;
+ } else
+ c4 = *(backPtr + _screenWide + 1);
+ } else
+ c4 = c3;
+
+ if (!transparent) {
+ uint32 r1 = _palCopy[c1][0];
+ uint32 g1 = _palCopy[c1][1];
+ uint32 b1 = _palCopy[c1][2];
+
+ uint32 r2 = _palCopy[c2][0];
+ uint32 g2 = _palCopy[c2][1];
+ uint32 b2 = _palCopy[c2][2];
+
+ uint32 r3 = _palCopy[c3][0];
+ uint32 g3 = _palCopy[c3][1];
+ uint32 b3 = _palCopy[c3][2];
+
+ uint32 r4 = _palCopy[c4][0];
+ uint32 g4 = _palCopy[c4][1];
+ uint32 b4 = _palCopy[c4][2];
+
+ uint32 r5 = (r1 * xFrac + r2 * (dstWidth - xFrac)) / dstWidth;
+ uint32 g5 = (g1 * xFrac + g2 * (dstWidth - xFrac)) / dstWidth;
+ uint32 b5 = (b1 * xFrac + b2 * (dstWidth - xFrac)) / dstWidth;
+
+ uint32 r6 = (r3 * xFrac + r4 * (dstWidth - xFrac)) / dstWidth;
+ uint32 g6 = (g3 * xFrac + g4 * (dstWidth - xFrac)) / dstWidth;
+ uint32 b6 = (b3 * xFrac + b4 * (dstWidth - xFrac)) / dstWidth;
+
+ uint32 r = (r5 * yFrac + r6 * (dstHeight - yFrac)) / dstHeight;
+ uint32 g = (g5 * yFrac + g6 * (dstHeight - yFrac)) / dstHeight;
+ uint32 b = (b5 * yFrac + b6 * (dstHeight - yFrac)) / dstHeight;
+
+ dst[y * dstWidth + x] = quickMatch(r, g, b);
+ } else
+ dst[y * dstWidth + x] = 0;
}
-
- free(newDst);
}
}
diff --git a/sword2/driver/sprite.cpp b/sword2/driver/sprite.cpp
index 776c1d9d55..601e003f5b 100644
--- a/sword2/driver/sprite.cpp
+++ b/sword2/driver/sprite.cpp
@@ -355,12 +355,10 @@ void Graphics::deleteSurface(byte *surface) {
int32 Graphics::drawSprite(SpriteInfo *s) {
byte *src, *dst;
byte *sprite, *newSprite;
- byte *backbuf = NULL;
uint16 scale;
int16 i, j;
uint16 srcPitch;
bool freeSprite = false;
- bool clipped = false;
Common::Rect rd, rs;
// -----------------------------------------------------------------
@@ -453,22 +451,18 @@ int32 Graphics::drawSprite(SpriteInfo *s) {
if (rd.top < 40) {
rs.top = 40 - rd.top;
rd.top = 40;
- clipped = true;
}
if (rd.bottom > 440) {
rd.bottom = 440;
rs.bottom = rs.top + (rd.bottom - rd.top);
- clipped = true;
}
if (rd.left < 0) {
rs.left = -rd.left;
rd.left = 0;
- clipped = true;
}
if (rd.right > 640) {
rd.right = 640;
rs.right = rs.left + (rd.right - rd.left);
- clipped = true;
}
// -----------------------------------------------------------------
@@ -476,10 +470,6 @@ int32 Graphics::drawSprite(SpriteInfo *s) {
// -----------------------------------------------------------------
if (scale != 256) {
- if ((_renderCaps & RDBLTFX_EDGEBLEND) && !clipped)
- backbuf = _buffer + _screenWide * rd.top + rd.left;
-
-
if (s->scaledWidth > SCALE_MAXWIDTH || s->scaledHeight > SCALE_MAXHEIGHT) {
if (freeSprite)
free(sprite);
@@ -493,16 +483,10 @@ int32 Graphics::drawSprite(SpriteInfo *s) {
return RDERR_OUTOFMEMORY;
}
- if (scale < 256) {
- squashImage(newSprite, s->scaledWidth, s->scaledWidth, s->scaledHeight, sprite, s->w, s->w, s->h, backbuf);
- } else {
- if (s->scale > 512) {
- if (freeSprite)
- free(sprite);
- return RDERR_INVALIDSCALING;
- }
- stretchImage(newSprite, s->scaledWidth, s->scaledWidth, s->scaledHeight, sprite, s->w, s->w, s->h, backbuf);
- }
+ if (_renderCaps & RDBLTFX_EDGEBLEND)
+ scaleImageGood(newSprite, s->scaledWidth, s->scaledWidth, s->scaledHeight, sprite, s->w, s->w, s->h, _buffer + _screenWide * rd.top + rd.left);
+ else
+ scaleImageFast(newSprite, s->scaledWidth, s->scaledWidth, s->scaledHeight, sprite, s->w, s->w, s->h);
if (freeSprite)
free(sprite);