summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBertram <bertram@cegetel.net>2009-07-24 22:59:13 +0200
committerBertram <bertram@cegetel.net>2009-07-24 22:59:13 +0200
commit8195e73cb801d56240beb966554a864729d9f20c (patch)
treef2a00036d15eaf70cb9abe4930b4199b1e5eae05 /src
parentea6f492198a03cffc3be47df000fa16dfc3b262f (diff)
downloadmana-client-8195e73cb801d56240beb966554a864729d9f20c.tar.gz
mana-client-8195e73cb801d56240beb966554a864729d9f20c.tar.bz2
mana-client-8195e73cb801d56240beb966554a864729d9f20c.tar.xz
mana-client-8195e73cb801d56240beb966554a864729d9f20c.zip
Made the wallpaper be rescaled when necessary under SDL and OpenGL.
The SDL methods to rescale the wallpaper has been optimized to permit rescaling at load time while OpenGL draws directly rescaled. Does someone know how to smooth the rescaled image under OpenGL?
Diffstat (limited to 'src')
-rw-r--r--src/CMakeLists.txt2
-rw-r--r--src/graphics.cpp41
-rw-r--r--src/graphics.h22
-rw-r--r--src/gui/widgets/desktop.cpp27
-rw-r--r--src/openglgraphics.cpp67
-rw-r--r--src/openglgraphics.h9
-rw-r--r--src/resources/image.cpp39
-rw-r--r--src/resources/image.h16
-rw-r--r--src/resources/resourcemanager.cpp13
-rw-r--r--src/resources/resourcemanager.h9
-rw-r--r--src/resources/sdlrescalefacility.cpp486
-rw-r--r--src/resources/sdlrescalefacility.h52
12 files changed, 776 insertions, 7 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 15109185..43726f9d 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -304,6 +304,8 @@ SET(SRCS
resources/resource.h
resources/resourcemanager.cpp
resources/resourcemanager.h
+ resources/sdlrescalefacility.h
+ resources/sdlrescalefacility.cpp
resources/soundeffect.h
resources/soundeffect.cpp
resources/spritedef.h
diff --git a/src/graphics.cpp b/src/graphics.cpp
index 58f643e9..b84e0bf6 100644
--- a/src/graphics.cpp
+++ b/src/graphics.cpp
@@ -120,11 +120,47 @@ bool Graphics::drawImage(Image *image, int x, int y)
return drawImage(image, 0, 0, x, y, image->mBounds.w, image->mBounds.h);
}
+bool Graphics::drawRescaledImage(Image *image, int srcX, int srcY,
+ int dstX, int dstY,
+ int width, int height,
+ int desiredWidth, int desiredHeight,
+ bool useColor)
+{
+ // Check that preconditions for blitting are met.
+ if (!mScreen || !image) return false;
+ if (!image->mImage) return false;
+
+ Image *tmpImage = image->SDLgetScaledImage(desiredWidth, desiredHeight);
+ bool returnValue = false;
+ if (!tmpImage) return false;
+ if (!tmpImage->mImage) return false;
+
+ dstX += mClipStack.top().xOffset;
+ dstY += mClipStack.top().yOffset;
+
+ srcX += image->mBounds.x;
+ srcY += image->mBounds.y;
+
+ SDL_Rect dstRect;
+ SDL_Rect srcRect;
+ dstRect.x = dstX; dstRect.y = dstY;
+ srcRect.x = srcX; srcRect.y = srcY;
+ srcRect.w = width;
+ srcRect.h = height;
+
+ returnValue = !(SDL_BlitSurface(tmpImage->mImage, &srcRect, mScreen, &dstRect) < 0);
+
+ delete tmpImage;
+
+ return returnValue;
+}
+
bool Graphics::drawImage(Image *image, int srcX, int srcY, int dstX, int dstY,
int width, int height, bool)
{
// Check that preconditions for blitting are met.
- if (!mScreen || !image || !image->mImage) return false;
+ if (!mScreen || !image) return false;
+ if (!image->mImage) return false;
dstX += mClipStack.top().xOffset;
dstY += mClipStack.top().yOffset;
@@ -154,7 +190,8 @@ void Graphics::drawImage(gcn::Image const *image, int srcX, int srcY,
void Graphics::drawImagePattern(Image *image, int x, int y, int w, int h)
{
// Check that preconditions for blitting are met.
- if (!mScreen || !image || !image->mImage) return;
+ if (!mScreen || !image) return;
+ if (!image->mImage) return;
const int iw = image->getWidth();
const int ih = image->getHeight();
diff --git a/src/graphics.h b/src/graphics.h
index d0e70c24..eca7e1a5 100644
--- a/src/graphics.h
+++ b/src/graphics.h
@@ -105,6 +105,28 @@ class Graphics : public gcn::SDLGraphics
int dstX, int dstY, int width, int height);
/**
+ * Draws a resclaled version of the image
+ */
+ bool drawRescaledImage(Image *image, int srcX, int srcY,
+ int dstX, int dstY,
+ int width, int height,
+ int desiredWidth, int desiredHeight)
+ { return drawRescaledImage(image, srcX, srcY,
+ dstX, dstY,
+ width, height,
+ desiredWidth, desiredHeight,
+ false); };
+
+ /**
+ * Draws a resclaled version of the image
+ */
+ virtual bool drawRescaledImage(Image *image, int srcX, int srcY,
+ int dstX, int dstY,
+ int width, int height,
+ int desiredWidth, int desiredHeight,
+ bool useColor = false);
+
+ /**
* Blits an image onto the screen.
*
* @return <code>true</code> if the image was blitted properly
diff --git a/src/gui/widgets/desktop.cpp b/src/gui/widgets/desktop.cpp
index a4164bcc..6633d2ce 100644
--- a/src/gui/widgets/desktop.cpp
+++ b/src/gui/widgets/desktop.cpp
@@ -74,9 +74,14 @@ void Desktop::draw(gcn::Graphics *graphics)
if (mWallpaper)
{
- g->drawImage(mWallpaper,
+ if (!mWallpaper->isAnOpenGLOne())
+ g->drawImage(mWallpaper,
(getWidth() - mWallpaper->getWidth()) / 2,
(getHeight() - mWallpaper->getHeight()) / 2);
+ else
+ g->drawRescaledImage(mWallpaper, 0, 0, 0, 0,
+ mWallpaper->getWidth(), mWallpaper->getHeight(),
+ getWidth(), getHeight(), false);
}
Container::draw(graphics);
@@ -87,13 +92,27 @@ void Desktop::setBestFittingWallpaper()
const std::string wallpaperName =
Wallpaper::getWallpaper(getWidth(), getHeight());
- Image *temp = ResourceManager::getInstance()->getImage(wallpaperName);
+ Image *nWallPaper = ResourceManager::getInstance()->getImage(wallpaperName);
- if (temp)
+ if (nWallPaper)
{
if (mWallpaper)
mWallpaper->decRef();
- mWallpaper = temp;
+
+ if (!nWallPaper->isAnOpenGLOne() && (nWallPaper->getWidth() != getWidth()
+ || nWallPaper->getHeight() != getHeight()))
+ {
+ // We rescale to obtain a fullscreen wallpaper...
+ Image *newRsclWlPpr = nWallPaper->SDLgetScaledImage(getWidth(), getHeight());
+ std::string idPath = nWallPaper->getIdPath();
+
+ // We replace the resource in the resource manager
+ nWallPaper->decRef();
+ ResourceManager::getInstance()->addResource(idPath, newRsclWlPpr);
+ mWallpaper = newRsclWlPpr;
+ }
+ else
+ mWallpaper = nWallPaper;
}
else
{
diff --git a/src/openglgraphics.cpp b/src/openglgraphics.cpp
index b9d837ad..5c9e2049 100644
--- a/src/openglgraphics.cpp
+++ b/src/openglgraphics.cpp
@@ -140,6 +140,42 @@ static inline void drawQuad(Image *image,
}
}
+static inline void drawRescaledQuad(Image *image,
+ int srcX, int srcY, int dstX, int dstY,
+ int width, int height,
+ int desiredWidth, int desiredHeight)
+{
+ if (image->getTextureType() == GL_TEXTURE_2D)
+ {
+ // Find OpenGL normalized texture coordinates.
+ float texX1 = srcX / (float) image->getTextureWidth();
+ float texY1 = srcY / (float) image->getTextureHeight();
+ float texX2 = (srcX + width) / (float) image->getTextureWidth();
+ float texY2 = (srcY + height) / (float) image->getTextureHeight();
+
+ glTexCoord2f(texX1, texY1);
+ glVertex2i(dstX, dstY);
+ glTexCoord2f(texX2, texY1);
+ glVertex2i(dstX + desiredWidth, dstY);
+ glTexCoord2f(texX2, texY2);
+ glVertex2i(dstX + desiredWidth, dstY + desiredHeight);
+ glTexCoord2f(texX1, texY2);
+ glVertex2i(dstX, dstY + desiredHeight);
+ }
+ else
+ {
+ glTexCoord2i(srcX, srcY);
+ glVertex2i(dstX, dstY);
+ glTexCoord2i(srcX + width, srcY);
+ glVertex2i(dstX + desiredWidth, dstY);
+ glTexCoord2i(srcX + width, srcY + height);
+ glVertex2i(dstX + desiredWidth, dstY + desiredHeight);
+ glTexCoord2i(srcX, srcY + height);
+ glVertex2i(dstX, dstY + desiredHeight);
+ }
+}
+
+
bool OpenGLGraphics::drawImage(Image *image, int srcX, int srcY,
int dstX, int dstY,
int width, int height, bool useColor)
@@ -168,6 +204,37 @@ bool OpenGLGraphics::drawImage(Image *image, int srcX, int srcY,
return true;
}
+bool OpenGLGraphics::drawRescaledImage(Image *image, int srcX, int srcY,
+ int dstX, int dstY,
+ int width, int height,
+ int desiredWidth, int desiredHeight,
+ bool useColor)
+{
+ if (!image)
+ return false;
+
+ srcX += image->mBounds.x;
+ srcY += image->mBounds.y;
+
+ if (!useColor)
+ glColor4f(1.0f, 1.0f, 1.0f, image->mAlpha);
+
+ glBindTexture(Image::mTextureType, image->mGLImage);
+
+ setTexturingAndBlending(true);
+
+ // Draw a textured quad.
+ glBegin(GL_QUADS);
+ drawRescaledQuad(image, srcX, srcY, dstX, dstY, width, height,
+ desiredWidth, desiredHeight);
+ glEnd();
+
+ if (!useColor)
+ glColor4ub(mColor.r, mColor.g, mColor.b, mColor.a);
+
+ return true;
+}
+
/* Optimising the functions that Graphics::drawImagePattern would call,
* so that glBegin...glEnd are outside the main loop. */
void OpenGLGraphics::drawImagePattern(Image *image, int x, int y, int w, int h)
diff --git a/src/openglgraphics.h b/src/openglgraphics.h
index dc748804..3553cac3 100644
--- a/src/openglgraphics.h
+++ b/src/openglgraphics.h
@@ -46,6 +46,15 @@ class OpenGLGraphics : public Graphics
int width, int height,
bool useColor);
+ /**
+ * Draws a resclaled version of the image
+ */
+ bool drawRescaledImage(Image *image, int srcX, int srcY,
+ int dstX, int dstY,
+ int width, int height,
+ int desiredWidth, int desiredHeight,
+ bool useColor);
+
void drawImagePattern(Image *image,
int x, int y,
int w, int h);
diff --git a/src/resources/image.cpp b/src/resources/image.cpp
index 0c542a8b..66f87ccb 100644
--- a/src/resources/image.cpp
+++ b/src/resources/image.cpp
@@ -26,6 +26,7 @@
#include "log.h"
#include <SDL_image.h>
+#include "resources/sdlrescalefacility.h"
#ifdef USE_OPENGL
bool Image::mUseOpenGL = false;
@@ -289,6 +290,15 @@ void Image::unload()
#endif
}
+bool Image::isAnOpenGLOne() const
+{
+#ifdef USE_OPENGL
+ return mUseOpenGL;
+#else
+ return false;
+#endif
+}
+
Image *Image::getSubImage(int x, int y, int width, int height)
{
// Create a new clipped sub-image
@@ -395,6 +405,34 @@ float Image::getAlpha() const
return mAlpha;
}
+Image* Image::SDLgetScaledImage(unsigned int width, unsigned int height)
+{
+ // No scaling on incorrect new values.
+ if (width == 0 || height == 0)
+ return NULL;
+
+ // No scaling when there is ... no different given size ...
+ if (width == getWidth() && height == getHeight())
+ return NULL;
+
+ Image* scaledImage = NULL;
+ SDL_Surface* scaledSurface = NULL;
+
+ if (mImage)
+ {
+ scaledSurface = _SDLzoomSurface(mImage,
+ (double) width / getWidth(),
+ (double) height / getHeight(),
+ 1);
+
+ // The load function takes of the SDL<->OpenGL implementation
+ // and about freeing the given SDL_surface*.
+ if (scaledSurface)
+ scaledImage = load(scaledSurface);
+ }
+ return scaledImage;
+}
+
#ifdef USE_OPENGL
void Image::setLoadAsOpenGL(bool useOpenGL)
{
@@ -469,4 +507,3 @@ Image *SubImage::getSubImage(int x, int y, int w, int h)
{
return mParent->getSubImage(mBounds.x + x, mBounds.y + y, w, h);
}
-
diff --git a/src/resources/image.h b/src/resources/image.h
index 4422fcc8..dc06a5f3 100644
--- a/src/resources/image.h
+++ b/src/resources/image.h
@@ -88,6 +88,16 @@ class Image : public Resource
static Image *load(SDL_Surface *);
/**
+ * Gets an scaled instance of an image.
+ *
+ * @param width The desired width of the scaled image.
+ * @param height The desired height of the scaled image.
+ *
+ * @return A new Image* object.
+ */
+ Image* SDLgetScaledImage(unsigned int width, unsigned int height);
+
+ /**
* Frees the resources created by SDL.
*/
virtual void unload();
@@ -105,6 +115,12 @@ class Image : public Resource
{ return mBounds.h; }
/**
+ * Tells if the image was loade using OpenGL or SDL
+ * @return true if OpenGL, false if SDL.
+ */
+ bool isAnOpenGLOne() const;
+
+ /**
* Creates a new image with the desired clipping rectangle.
*
* @return <code>NULL</code> if creation failed and a valid
diff --git a/src/resources/resourcemanager.cpp b/src/resources/resourcemanager.cpp
index 0b8d6c35..bc3267da 100644
--- a/src/resources/resourcemanager.cpp
+++ b/src/resources/resourcemanager.cpp
@@ -214,6 +214,19 @@ std::string ResourceManager::getPath(const std::string &file)
return path;
}
+bool ResourceManager::addResource(const std::string &idPath,
+ Resource* resource)
+{
+ if (resource)
+ {
+ resource->incRef();
+ resource->mIdPath = idPath;
+ mResources[idPath] = resource;
+ return true;
+ }
+ return false;
+}
+
Resource *ResourceManager::get(const std::string &idPath, generator fun,
void *data)
{
diff --git a/src/resources/resourcemanager.h b/src/resources/resourcemanager.h
index b2ad3069..88fd60fc 100644
--- a/src/resources/resourcemanager.h
+++ b/src/resources/resourcemanager.h
@@ -125,6 +125,15 @@ class ResourceManager
Resource *load(const std::string &path, loader fun);
/**
+ * Adds a preformatted resource to the resource map.
+ *
+ * @param path The file name.
+ * @param Resource The Resource to add.
+ * @return true if successfull, false otherwise.
+ */
+ bool addResource(const std::string &idPath, Resource* resource);
+
+ /**
* Copies a file from one place to another (useful for extracting
* raw files from a zip archive, for example)
*
diff --git a/src/resources/sdlrescalefacility.cpp b/src/resources/sdlrescalefacility.cpp
new file mode 100644
index 00000000..cc478483
--- /dev/null
+++ b/src/resources/sdlrescalefacility.cpp
@@ -0,0 +1,486 @@
+/*
+ * The Mana World
+ * Copyright (C) 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the Low GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Source code taken from:
+ *
+ * SDL_rotozoom - rotozoomer
+ *
+ * LGPL (c) A. Schiffler
+ *
+ */
+
+#include "sdlrescalefacility.h"
+
+#define VALUE_LIMIT 0.001
+
+typedef struct tColorRGBA {
+Uint8 r;
+Uint8 g;
+Uint8 b;
+Uint8 a;
+} tColorRGBA;
+
+void zoomSurfaceSize(int width, int height, double zoomx, double zoomy, int *dstwidth, int *dstheight)
+{
+ /*
+ * Sanity check zoom factors
+ */
+ if (zoomx < VALUE_LIMIT) {
+ zoomx = VALUE_LIMIT;
+ }
+ if (zoomy < VALUE_LIMIT) {
+ zoomy = VALUE_LIMIT;
+ }
+
+ /*
+ * Calculate target size
+ */
+ *dstwidth = (int) ((double) width * zoomx);
+ *dstheight = (int) ((double) height * zoomy);
+ if (*dstwidth < 1) {
+ *dstwidth = 1;
+ }
+ if (*dstheight < 1) {
+ *dstheight = 1;
+ }
+}
+
+int zoomSurfaceRGBA(SDL_Surface * src, SDL_Surface * dst, int flipx, int flipy, int smooth)
+{
+ int x, y, sx, sy, *sax, *say, *csax, *csay, csx, csy, ex, ey, t1, t2, sstep, lx, ly;
+ tColorRGBA *c00, *c01, *c10, *c11, *cswap;
+ tColorRGBA *sp, *csp, *dp;
+ int dgap;
+
+ /*
+ * Variable setup
+ */
+ if (smooth) {
+ /*
+ * For interpolation: assume source dimension is one pixel
+ */
+ /*
+ * smaller to avoid overflow on right and bottom edge.
+ */
+ sx = (int) (65536.0 * (float) (src->w - 1) / (float) dst->w);
+ sy = (int) (65536.0 * (float) (src->h - 1) / (float) dst->h);
+ } else {
+ sx = (int) (65536.0 * (float) src->w / (float) dst->w);
+ sy = (int) (65536.0 * (float) src->h / (float) dst->h);
+ }
+
+ /*
+ * Allocate memory for row increments
+ */
+ if ((sax = (int *) malloc((dst->w + 1) * sizeof(Uint32))) == NULL) {
+ return (-1);
+ }
+ if ((say = (int *) malloc((dst->h + 1) * sizeof(Uint32))) == NULL) {
+ free(sax);
+ return (-1);
+ }
+
+ /*
+ * Precalculate row increments
+ */
+ sp = csp = (tColorRGBA *) src->pixels;
+ dp = (tColorRGBA *) dst->pixels;
+
+ if (flipx) csp += (src->w-1);
+ if (flipy) csp += (src->pitch*(src->h-1));
+
+ csx = 0;
+ csax = sax;
+ for (x = 0; x <= dst->w; x++) {
+ *csax = csx;
+ csax++;
+ csx &= 0xffff;
+ csx += sx;
+ }
+ csy = 0;
+ csay = say;
+ for (y = 0; y <= dst->h; y++) {
+ *csay = csy;
+ csay++;
+ csy &= 0xffff;
+ csy += sy;
+ }
+
+ dgap = dst->pitch - dst->w * 4;
+
+ /*
+ * Switch between interpolating and non-interpolating code
+ */
+ if (smooth) {
+
+ /*
+ * Interpolating Zoom
+ */
+
+ /*
+ * Scan destination
+ */
+ ly = 0;
+ csay = say;
+ for (y = 0; y < dst->h; y++) {
+ /*
+ * Setup color source pointers
+ */
+ c00 = csp;
+ c01 = csp;
+ c01++;
+ c10 = (tColorRGBA *) ((Uint8 *) csp + src->pitch);
+ c11 = c10;
+ c11++;
+ csax = sax;
+ 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;
+ }
+ lx = 0;
+ for (x = 0; x < dst->w; x++) {
+ /*
+ * Interpolate colors
+ */
+ ex = (*csax & 0xffff);
+ ey = (*csay & 0xffff);
+ 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 pointers
+ */
+ csax++;
+ sstep = (*csax >> 16);
+ lx += sstep;
+ if (lx >= src->w) sstep = 0;
+ if (flipx) sstep = -sstep;
+ c00 += sstep;
+ c01 += sstep;
+ c10 += sstep;
+ c11 += sstep;
+ /*
+ * Advance destination pointer
+ */
+ dp++;
+ }
+ /*
+ * Advance source pointer
+ */
+ csay++;
+ sstep = (*csay >> 16);
+ ly += sstep;
+ if (ly >= src->h) sstep = 0;
+ sstep *= src->pitch;
+ if (flipy) sstep = -sstep;
+ csp = (tColorRGBA *) ((Uint8 *) csp + sstep);
+
+ /*
+ * Advance destination pointers
+ */
+ dp = (tColorRGBA *) ((Uint8 *) dp + dgap);
+ }
+ } else {
+
+ /*
+ * Non-Interpolating Zoom
+ */
+
+ csay = say;
+ for (y = 0; y < dst->h; y++) {
+ sp = csp;
+ csax = sax;
+ for (x = 0; x < dst->w; x++) {
+ /*
+ * Draw
+ */
+ *dp = *sp;
+ /*
+ * Advance source pointers
+ */
+ csax++;
+ sstep = (*csax >> 16);
+ if (flipx) sstep = -sstep;
+ sp += sstep;
+ /*
+ * Advance destination pointer
+ */
+ dp++;
+ }
+ /*
+ * Advance source pointer
+ */
+ csay++;
+ sstep = (*csay >> 16) * src->pitch;
+ if (flipy) sstep = -sstep;
+ csp = (tColorRGBA *) ((Uint8 *) csp + sstep);
+
+ /*
+ * Advance destination pointers
+ */
+ dp = (tColorRGBA *) ((Uint8 *) dp + dgap);
+ }
+ }
+
+ /*
+ * Remove temp arrays
+ */
+ free(sax);
+ free(say);
+
+ return (0);
+}
+
+
+
+int zoomSurfaceY(SDL_Surface * src, SDL_Surface * dst, int flipx, int flipy)
+{
+ Uint32 x, y, sx, sy, *sax, *say, *csax, *csay, csx, csy, sstep;
+ Uint8 *sp, *dp, *csp;
+ int dgap;
+
+ /*
+ * Variable setup
+ */
+ sx = (Uint32) (65536.0 * (float) src->w / (float) dst->w);
+ sy = (Uint32) (65536.0 * (float) src->h / (float) dst->h);
+
+
+ /*
+ * Allocate memory for row increments
+ */
+ if ((sax = (Uint32 *) malloc((dst->w + 1) * sizeof(Uint32))) == NULL) {
+ return (-1);
+ }
+ if ((say = (Uint32 *) malloc((dst->h + 1) * sizeof(Uint32))) == NULL) {
+ free(sax);
+ return (-1);
+ }
+
+ /*
+ * Pointer setup
+ */
+ sp = csp = (Uint8 *) src->pixels;
+ dp = (Uint8 *) dst->pixels;
+ dgap = dst->pitch - dst->w;
+
+ if (flipx) csp += (src->w-1);
+ if (flipy) csp = ( (Uint8*)csp + src->pitch*(src->h-1) );
+
+ /*
+ * Precalculate row increments
+ */
+ csx = 0;
+ csax = sax;
+ for (x = 0; x <= dst->w; x++) {
+ *csax = csx;
+ csax++;
+ csx &= 0xffff;
+ csx += sx;
+ }
+ csy = 0;
+ csay = say;
+ for (y = 0; y <= dst->h; y++) {
+ *csay = csy;
+ csay++;
+ csy &= 0xffff;
+ csy += sy;
+ }
+
+
+ /*
+ * Draw
+ */
+ csay = say;
+ for (y = 0; y < dst->h; y++) {
+ csax = sax;
+ sp = csp;
+ for (x = 0; x < dst->w; x++) {
+ /*
+ * Draw
+ */
+ *dp = *sp;
+ /*
+ * Advance source pointers
+ */
+ csax++;
+ sstep = (*csax >> 16);
+ if (flipx) sstep = -sstep;
+ sp += sstep;
+ /*
+ * Advance destination pointer
+ */
+ dp++;
+ }
+ /*
+ * Advance source pointer (for row)
+ */
+ csay++;
+ sstep = (*csay >> 16) * src->pitch;
+ if (flipy) sstep = -sstep;
+ csp = ((Uint8 *) csp + sstep);
+
+ /*
+ * Advance destination pointers
+ */
+ dp += dgap;
+ }
+
+ /*
+ * Remove temp arrays
+ */
+ free(sax);
+ free(say);
+
+ return (0);
+}
+
+
+
+SDL_Surface *_SDLzoomSurface(SDL_Surface * src, double zoomx, double zoomy, int smooth)
+{
+ SDL_Surface *rz_src;
+ SDL_Surface *rz_dst;
+ int dstwidth, dstheight;
+ int is32bit;
+ int i, src_converted;
+ int flipx, flipy;
+
+ /*
+ * Sanity check
+ */
+ if (src == NULL)
+ return (NULL);
+
+ /*
+ * Determine if source surface is 32bit or 8bit
+ */
+ is32bit = (src->format->BitsPerPixel == 32);
+ if ((is32bit) || (src->format->BitsPerPixel == 8)) {
+ /*
+ * Use source surface 'as is'
+ */
+ rz_src = src;
+ src_converted = 0;
+ } else {
+ /*
+ * New source surface is 32bit with a defined RGBA ordering
+ */
+ rz_src =
+ SDL_CreateRGBSurface(SDL_SWSURFACE, src->w, src->h, 32,
+#if SDL_BYTEORDER == SDL_LIL_ENDIAN
+ 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000
+#else
+ 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff
+#endif
+ );
+ SDL_BlitSurface(src, NULL, rz_src, NULL);
+ src_converted = 1;
+ is32bit = 1;
+ }
+
+ flipx = (zoomx<0.0);
+ if (flipx) zoomx = -zoomx;
+ flipy = (zoomy<0.0);
+ if (flipy) zoomy = -zoomy;
+
+ /* Get size if target */
+ zoomSurfaceSize(rz_src->w, rz_src->h, zoomx, zoomy, &dstwidth, &dstheight);
+
+ /*
+ * Alloc space to completely contain the zoomed surface
+ */
+ rz_dst = NULL;
+ if (is32bit) {
+ /*
+ * Target surface is 32bit with source RGBA/ABGR ordering
+ */
+ rz_dst =
+ SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight, 32,
+ rz_src->format->Rmask, rz_src->format->Gmask,
+ rz_src->format->Bmask, rz_src->format->Amask);
+ } else {
+ /*
+ * Target surface is 8bit
+ */
+ rz_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight, 8, 0, 0, 0, 0);
+ }
+
+ /*
+ * Lock source surface
+ */
+ SDL_LockSurface(rz_src);
+ /*
+ * Check which kind of surface we have
+ */
+ if (is32bit) {
+ /*
+ * Call the 32bit transformation routine to do the zooming (using alpha)
+ */
+ zoomSurfaceRGBA(rz_src, rz_dst, flipx, flipy, smooth);
+ /*
+ * Turn on source-alpha support
+ */
+ SDL_SetAlpha(rz_dst, SDL_SRCALPHA, 255);
+ } else {
+ /*
+ * Copy palette and colorkey info
+ */
+ for (i = 0; i < rz_src->format->palette->ncolors; i++) {
+ rz_dst->format->palette->colors[i] = rz_src->format->palette->colors[i];
+ }
+ rz_dst->format->palette->ncolors = rz_src->format->palette->ncolors;
+ /*
+ * Call the 8bit transformation routine to do the zooming
+ */
+ zoomSurfaceY(rz_src, rz_dst, flipx, flipy);
+ SDL_SetColorKey(rz_dst, SDL_SRCCOLORKEY | SDL_RLEACCEL, rz_src->format->colorkey);
+ }
+ /*
+ * Unlock source surface
+ */
+ SDL_UnlockSurface(rz_src);
+
+ /*
+ * Cleanup temp surface
+ */
+ if (src_converted) {
+ SDL_FreeSurface(rz_src);
+ }
+
+ /*
+ * Return destination surface
+ */
+ return (rz_dst);
+}
diff --git a/src/resources/sdlrescalefacility.h b/src/resources/sdlrescalefacility.h
new file mode 100644
index 00000000..597e6933
--- /dev/null
+++ b/src/resources/sdlrescalefacility.h
@@ -0,0 +1,52 @@
+/*
+ * The Mana World
+ * Copyright (C) 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the Low GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Source code taken from:
+ *
+ * SDL_rotozoom - rotozoomer
+ *
+ * LGPL (c) A. Schiffler
+ *
+ */
+
+#ifndef SDLRESCALEFACILITY_H
+#define SDLRESCALEFACILITY_H
+
+#include <SDL.h>
+#include "image.h"
+
+/**
+ * _SDLzoomSurface is internally used by Image::getScaledImage() to provide
+ * a rescaled copy of its internal mImage member.
+ *
+ * @see Image::getScaledImage() for more details
+ *
+ * @param src the original surface to rescale
+ * @param zoomx the zoom factor used to rescale the surface horizontally. 1.0 doesn't rescale.
+ * A value lesser than 1.O shrink the image.
+ * @param zoomy the zoom factor used to rescale the surface vertically.
+ * @param smooth transform the scaled surface into a 32bit aliased image to smooth the rescaling.
+ *
+ * @return SDL_Surface The rescaled surface.
+ */
+
+SDL_Surface *_SDLzoomSurface(SDL_Surface * src, double zoomx, double zoomy, int smooth);
+
+#endif \ No newline at end of file