From 86441fda9c561dd264039edc68ddabbf7cb54ce2 Mon Sep 17 00:00:00 2001
From: Bjørn Lindeijer <bjorn@lindeijer.nl>
Date: Thu, 18 Oct 2007 18:39:48 +0000
Subject: Merged removal of dependency on Guichan OpenGL from trunk to 0.0
 branch, including optimization of OpenGL memory usage on modern OpenGL
 drivers. Patches by Guillaume Melquiond.

---
 ChangeLog                              |  32 ++++++--
 configure.ac                           |  18 ++---
 src/CMakeLists.txt                     |  24 +++---
 src/Makefile.am                        |  14 ++--
 src/graphics.cpp                       |  15 +++-
 src/graphics.h                         |   9 ++-
 src/gui/gui.cpp                        |  25 ++----
 src/gui/gui.h                          |   2 -
 src/main.cpp                           |  19 +++--
 src/main.h                             |  13 +++-
 src/openglgraphics.cpp                 | 135 ++++++++++++++++++---------------
 src/openglgraphics.h                   |  10 +--
 src/resources/image.cpp                |  66 ++++++++++------
 src/resources/image.h                  |   9 +++
 src/resources/imageloader.cpp          |  99 ++++++++++++++++++++++++
 src/resources/imageloader.h            |  69 +++++++++++++++++
 src/resources/iteminfo.cpp             |   1 +
 src/resources/openglsdlimageloader.cpp |  39 ----------
 src/resources/openglsdlimageloader.h   |  38 ----------
 src/resources/sdlimageloader.cpp       |  34 ---------
 src/resources/sdlimageloader.h         |  37 ---------
 src/utils/minmax.h                     |   2 +
 22 files changed, 397 insertions(+), 313 deletions(-)
 create mode 100644 src/resources/imageloader.cpp
 create mode 100644 src/resources/imageloader.h
 delete mode 100644 src/resources/openglsdlimageloader.cpp
 delete mode 100644 src/resources/openglsdlimageloader.h
 delete mode 100644 src/resources/sdlimageloader.cpp
 delete mode 100644 src/resources/sdlimageloader.h

diff --git a/ChangeLog b/ChangeLog
index 9d844460..d75f461a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -58,11 +58,11 @@
 
 2007-09-08  Philipp Sehmisch  <tmw@crushnet.org>
 
-	* data/graphics/particles/aniblaze.png, 
+	* data/graphics/particles/aniblaze.png,
 	data/graphics/particles/cookingfire.particle.xml,
 	data/graphics/particles/fireplace.particle.xml,
-	data/graphics/particles/flame.particle.xml:
-	Improved fire effects by using animated particles.
+	data/graphics/particles/flame.particle.xml: Improved fire effects by
+	using animated particles.
 
 2007-09-06  Philipp Sehmisch  <tmw@crushnet.org>
 
@@ -150,6 +150,28 @@
 	* src/gui/updatewindow.cpp, src/main.cpp, tmw.cbp: Removed home dir
 	from config file to avoid encoding issues.
 
+2007-08-26  Guillaume Melquiond  <guillaume.melquiond@gmail.com>
+
+	* src/gui/button.cpp: Fixed incorrect button dimensions, as they mess
+	OpenGL display with rectangle textures.
+	* src/graphics.cpp, src/openglgraphics.h, src/graphics.h,
+	src/openglgraphics.cpp: Fixed fonts not being recolored by adding an
+	explicit parameter to require it.
+
+2007-08-25  Guillaume Melquiond  <guillaume.melquiond@gmail.com>
+
+	* configure.ac: Removed dependency on Guichan's OpenGL library.
+	* src/Makefile.am, src/resources/sdlimageloader.cpp,
+	src/resources/sdlimageloader.h, src/resources/openglsdlimageloader.h,
+	src/resources/openglsdlimageloader.cpp, src/resources/imageloader.cpp,
+	src/resources/imageloader.h, src/gui/gui.cpp, src/gui/gui.h: Replaced
+	Guichan's image loaders with our owns, so that we have control over all
+	the images used as textures.
+	* src/resources/image.cpp, src/openglgraphics.h, src/resources/image.h,
+	src/openglgraphics.cpp, src/graphics.cpp, src/graphics.h: Added support
+	for rectangle OpenGL textures when available, in order to reduce video
+	memory usage.
+
 2007-08-24  Bjørn Lindeijer  <bjorn@lindeijer.nl>
 
 	* src/gui/gui.h, src/gui/gui.cpp: Removed useless logic method and
@@ -4270,9 +4292,9 @@
 	src/gui/status.h: Improving General Layout.
 	* src/games.cpp, src/playerinfo.h, src/gui/char_server.cpp,
 	src/gui/char_select.cpp, src/gui/ministatus.cpp, src/gui/skill.cpp,
-	src/gui/status.cpp, src/gui/status.h : Now the derived stats values
+	src/gui/status.cpp, src/gui/status.h: Now the derived stats values
 	are got from the server, and then, are correct ones.
-	* src/gui/minimap.cpp : Only shows the Minimap Window if there's
+	* src/gui/minimap.cpp: Only shows the Minimap Window if there's
 	actually a minimap to the current map.
 	* src/gui/status.cpp, src/game.cpp: The derived stats are now updated
 	correctly upon equipping/unequipping.
diff --git a/configure.ac b/configure.ac
index 1d420d80..382a26ba 100755
--- a/configure.ac
+++ b/configure.ac
@@ -5,7 +5,6 @@ AC_LANG_CPLUSPLUS
 
 # Checks for programs.
 AC_PROG_CXX
-AC_PROG_CC
 AC_PROG_INSTALL
 AC_PROG_MAKE_SET
 
@@ -25,7 +24,7 @@ AC_CHECK_FUNCS([atexit floor getcwd gethostbyname memset mkdir select socket])
 
 # Checks for libraries
 AC_CHECK_LIB([pthread], [pthread_create], ,
-AC_MSG_ERROR([ *** Unable to find pthread library ]))
+AC_MSG_ERROR([ *** Unable to find pthread library]))
 
 AC_CHECK_LIB([guichan], [gcnGuichanVersion], ,
 AC_MSG_ERROR([ *** Unable to find Guichan library (guichan.sf.net)]))
@@ -33,9 +32,6 @@ AC_MSG_ERROR([ *** Unable to find Guichan library (guichan.sf.net)]))
 #AC_CHECK_LIB([guichan_sdl], [gcnSDL], ,
 #AC_MSG_ERROR([ *** Unable to find Guichan SDL library (guichan.sf.net)]))
 
-#AC_CHECK_LIB([guichan_opengl], [gcnOpenGL], ,
-#AC_MSG_ERROR([ *** Unable to find Guichan OpenGL library (guichan.sf.net)]))
-
 AC_CHECK_LIB([z], [inflate], ,
 AC_MSG_ERROR([ *** Unable to find zlib (http://www.gzip.org/zlib/)]))
 
@@ -59,9 +55,8 @@ AC_CHECK_LIB(SDL_image, IMG_LoadPNG_RW, ,
 AC_MSG_ERROR([ *** Unable to find SDL_image library with PNG support
 (http://www.libsdl.org/projects/SDL_image/)]))
 
-AC_CHECK_LIB(SDL_mixer, Mix_OpenAudio, ,
-AC_MSG_ERROR([ *** Unable to find SDL_mixer library
-(http://www.libsdl.org/projects/SDL_mixer/)]))
+AC_CHECK_LIB([SDL_mixer], [Mix_OpenAudio], ,
+AC_MSG_ERROR([ *** Unable to find SDL_mixer library (http://www.libsdl.org/projects/SDL_mixer/)]))
 
 AC_CHECK_LIB(SDL_net, SDLNet_Init, ,
 AC_MSG_ERROR([ *** Unable to find SDL_net library]))
@@ -82,10 +77,9 @@ if test "x$with_opengl" == "xno"; then
     with_opengl=no
 else
     with_opengl=yes
-    OPENGL_CFLAGS=' -DUSE_OPENGL'
-    OPENGL_LIBS=' -lGL -lguichan_opengl'
-    AC_SUBST(OPENGL_CFLAGS)
-    AC_SUBST(OPENGL_LIBS)
+    AC_CHECK_LIB([GL], [glBegin], ,
+    AC_MSG_ERROR([ *** Unable to find OpenGL library]))
+    AC_DEFINE(USE_OPENGL, 1, [Defines if tmw should use an OpenGL display])
 fi
 
 # Search for sdl-config
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 86d446b6..08a3b2a1 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -223,38 +223,36 @@ SET(SRCS
     resources/ambientoverlay.h
     resources/animation.cpp
     resources/animation.h
+    resources/buddylist.cpp
+    resources/buddylist.h
     resources/image.cpp
     resources/image.h
+    resources/imageloader.cpp
+    resources/imageloader.h
+    resources/imageset.h
+    resources/imageset.cpp
     resources/imagewriter.cpp
     resources/imagewriter.h
     resources/itemdb.cpp
     resources/itemdb.h
-    resources/iteminfo.h
     resources/iteminfo.cpp
+    resources/iteminfo.h
     resources/mapreader.cpp
     resources/mapreader.h
-    resources/monsterdb.h
     resources/monsterdb.cpp
-    resources/monsterinfo.h
+    resources/monsterdb.h
     resources/monsterinfo.cpp
-    resources/music.h
+    resources/monsterinfo.h
     resources/music.cpp
-    resources/openglsdlimageloader.h
-    resources/openglsdlimageloader.cpp
+    resources/music.h
     resources/resource.cpp
     resources/resource.h
     resources/resourcemanager.cpp
     resources/resourcemanager.h
-    resources/sdlimageloader.h
-    resources/sdlimageloader.cpp
-    resources/soundeffect.h
     resources/soundeffect.cpp
+    resources/soundeffect.h
     resources/spritedef.h
     resources/spritedef.cpp
-    resources/imageset.h
-    resources/imageset.cpp
-    resources/buddylist.h
-    resources/buddylist.cpp
     utils/base64.cpp
     utils/base64.h
     utils/dtor.h
diff --git a/src/Makefile.am b/src/Makefile.am
index 6d5ef196..1a121367 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -175,6 +175,10 @@ tmw_SOURCES = gui/widgets/resizegrip.cpp \
 	      resources/animation.h \
 	      resources/image.cpp \
 	      resources/image.h \
+	      resources/imageloader.cpp \
+	      resources/imageloader.h \
+	      resources/imageset.h \
+	      resources/imageset.cpp \
 	      resources/imagewriter.cpp \
 	      resources/imagewriter.h \
 	      resources/itemdb.cpp \
@@ -189,20 +193,14 @@ tmw_SOURCES = gui/widgets/resizegrip.cpp \
 	      resources/monsterinfo.cpp \
 	      resources/music.h \
 	      resources/music.cpp \
-	      resources/openglsdlimageloader.h \
-	      resources/openglsdlimageloader.cpp \
 	      resources/resource.cpp \
 	      resources/resource.h \
 	      resources/resourcemanager.cpp \
 	      resources/resourcemanager.h \
-	      resources/sdlimageloader.h \
-	      resources/sdlimageloader.cpp \
 	      resources/soundeffect.h \
 	      resources/soundeffect.cpp \
 	      resources/spritedef.h \
 	      resources/spritedef.cpp \
-	      resources/imageset.h \
-	      resources/imageset.cpp \
 	      resources/buddylist.h \
 	      resources/buddylist.cpp \
 	      utils/base64.cpp \
@@ -291,6 +289,6 @@ INCLUDES =					\
 
 # the library search path.
 tmw_LDFLAGS = $(all_libraries) $(LIBSDL_RPATH) `pkg-config --libs libxml-2.0`
-tmw_CXXFLAGS = -Wall $(OPENGL_CFLAGS) $(LIBSDL_CFLAGS) `pkg-config --cflags libxml-2.0` $(CURL_CFLAGS)
-tmw_LDADD = $(LIBSDL_LIBS) -lguichan_sdl $(OPENGL_LIBS) $(CURL_LIBS)
+tmw_CXXFLAGS = -Wall $(LIBSDL_CFLAGS) `pkg-config --cflags libxml-2.0` $(CURL_CFLAGS)
+tmw_LDADD = $(LIBSDL_LIBS) -lguichan_sdl $(CURL_LIBS)
 tmw_TARGET = tmw
diff --git a/src/graphics.cpp b/src/graphics.cpp
index 1e31f903..586f9f49 100644
--- a/src/graphics.cpp
+++ b/src/graphics.cpp
@@ -21,11 +21,13 @@
  *  $Id$
  */
 
-#include "graphics.h"
+#include <cassert>
 
+#include "graphics.h"
 #include "log.h"
 
 #include "resources/image.h"
+#include "resources/imageloader.h"
 
 Graphics::Graphics():
     mScreen(0)
@@ -125,7 +127,7 @@ bool Graphics::drawImage(Image *image, int x, int y)
 }
 
 bool Graphics::drawImage(Image *image, int srcX, int srcY, int dstX, int dstY,
-        int width, int height)
+        int width, int height, bool)
 {
     // Check that preconditions for blitting are met.
     if (!mScreen || !image || !image->mImage) return false;
@@ -146,6 +148,15 @@ bool Graphics::drawImage(Image *image, int srcX, int srcY, int dstX, int dstY,
     return !(SDL_BlitSurface(image->mImage, &srcRect, mScreen, &dstRect) < 0);
 }
 
+void Graphics::drawImage(gcn::Image const *image, int srcX, int srcY,
+               int dstX, int dstY, int width, int height)
+{
+    ProxyImage const *srcImage =
+        dynamic_cast< ProxyImage const * >(image);
+    assert(srcImage);
+    drawImage(srcImage->getImage(), srcX, srcY, dstX, dstY, width, height, true);
+}
+
 void Graphics::drawImagePattern(Image *image, int x, int y, int w, int h)
 {
     int iw = image->getWidth();
diff --git a/src/graphics.h b/src/graphics.h
index 4637973f..564826a2 100644
--- a/src/graphics.h
+++ b/src/graphics.h
@@ -85,6 +85,12 @@ class Graphics : public gcn::SDLGraphics {
          */
         bool drawImage(Image *image, int x, int y);
 
+        /**
+         * Overrides with our own drawing method.
+         */
+        void drawImage(gcn::Image const *image, int srcX, int srcY,
+                       int dstX, int dstY, int width, int height);
+
         /**
          * Blits an image onto the screen.
          *
@@ -95,7 +101,8 @@ class Graphics : public gcn::SDLGraphics {
         drawImage(Image *image,
                   int srcX, int srcY,
                   int dstX, int dstY,
-                  int width, int height);
+                  int width, int height,
+                  bool useColor = false);
 
         virtual void
         drawImagePattern(Image *image,
diff --git a/src/gui/gui.cpp b/src/gui/gui.cpp
index a83f794c..db0b9f80 100644
--- a/src/gui/gui.cpp
+++ b/src/gui/gui.cpp
@@ -30,14 +30,10 @@
 // Should stay here because of Guichan being sensitive to headers order
 #include <guichan/sdl/sdlinput.hpp>
 
-#ifdef USE_OPENGL
-#include "../resources/openglsdlimageloader.h"
-#endif
-
 #include "focushandler.h"
+#include "viewport.h"
 #include "window.h"
 #include "windowcontainer.h"
-#include "viewport.h"
 
 #include "../configlistener.h"
 #include "../configuration.h"
@@ -46,7 +42,7 @@
 
 #include "../resources/imageset.h"
 #include "../resources/resourcemanager.h"
-#include "../resources/sdlimageloader.h"
+#include "../resources/imageloader.h"
 
 // Guichan stuff
 Gui *gui;
@@ -79,7 +75,6 @@ class GuiConfigListener : public ConfigListener
 };
 
 Gui::Gui(Graphics *graphics):
-    mHostImageLoader(NULL),
     mCustomCursor(false),
     mMouseCursors(NULL),
     mCursorType(CURSOR_POINTER)
@@ -89,24 +84,16 @@ Gui::Gui(Graphics *graphics):
     setGraphics(graphics);
 
     // Set image loader
-#ifdef USE_OPENGL
-    if (config.getValue("opengl", 0)) {
-        mImageLoader = new OpenGLSDLImageLoader();
-    } else
-#endif
-    {
-        mImageLoader = new SDLImageLoader();
-    }
+    static ImageLoader imageLoader;
+    gcn::Image::setImageLoader(&imageLoader);
 
     // Set input
     guiInput = new gcn::SDLInput();
     setInput(guiInput);
 
-    gcn::Image::setImageLoader(mImageLoader);
-
     // Set focus handler
     delete mFocusHandler;
-    mFocusHandler = new FocusHandler();
+    mFocusHandler = new FocusHandler;
 
     // Initialize top GUI widget
     WindowContainer *guiTop = new WindowContainer();
@@ -187,8 +174,6 @@ Gui::~Gui()
     delete speechFont;
     delete viewport;
     delete mTop;
-    delete mImageLoader;
-    delete mHostImageLoader;
 
     delete guiInput;
 }
diff --git a/src/gui/gui.h b/src/gui/gui.h
index c709893f..1e4b9348 100644
--- a/src/gui/gui.h
+++ b/src/gui/gui.h
@@ -98,8 +98,6 @@ class Gui : public gcn::Gui
 
     private:
         GuiConfigListener *mConfigListener;
-        gcn::ImageLoader *mHostImageLoader;   /**< For loading images in GL */
-        gcn::ImageLoader *mImageLoader;       /**< For loading images */
         gcn::Font *mGuiFont;                  /**< The global GUI font */
         bool mCustomCursor;                   /**< Show custom cursor */
         ImageSet *mMouseCursors;              /**< Mouse cursor images */
diff --git a/src/main.cpp b/src/main.cpp
index c6544017..be36ac4f 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -288,17 +288,18 @@ void init_engine(const Options &options)
     graphics = new Graphics();
 #endif
 
-    int width = (int)config.getValue("screenwidth", 800);
-    int height = (int)config.getValue("screenheight", 600);
+    int width = (int) config.getValue("screenwidth", defaultScreenWidth);
+    int height = (int) config.getValue("screenheight", defaultScreenHeight);
     int bpp = 0;
-    bool fullscreen = ((int)config.getValue("screen", 0) == 1);
-    bool hwaccel = ((int)config.getValue("hwaccel", 0) == 1);
+    bool fullscreen = ((int) config.getValue("screen", 0) == 1);
+    bool hwaccel = ((int) config.getValue("hwaccel", 0) == 1);
 
     // Try to set the desired video mode
     if (!graphics->setVideoMode(width, height, bpp, fullscreen, hwaccel))
     {
-        std::cerr << "Couldn't set " << width << "x" << height << "x" <<
-            bpp << " video mode: " << SDL_GetError() << std::endl;
+        std::cerr << "Couldn't set "
+                  << width << "x" << height << "x" << bpp << " video mode: "
+                  << SDL_GetError() << std::endl;
         exit(1);
     }
 
@@ -316,8 +317,10 @@ void init_engine(const Options &options)
         if (config.getValue("sound", 0) == 1) {
             sound.init();
         }
-        sound.setSfxVolume((int) config.getValue("sfxVolume", 100));
-        sound.setMusicVolume((int) config.getValue("musicVolume", 60));
+        sound.setSfxVolume((int) config.getValue("sfxVolume",
+                    defaultSfxVolume));
+        sound.setMusicVolume((int) config.getValue("musicVolume",
+                    defaultMusicVolume));
     }
     catch (const char *err) {
         state = ERROR_STATE;
diff --git a/src/main.h b/src/main.h
index 5787756a..c18a2ddd 100644
--- a/src/main.h
+++ b/src/main.h
@@ -36,7 +36,9 @@
 #define TMW_DATADIR ""
 #endif
 
-
+/*
+ * Client different States
+ */
 enum {
     EXIT_STATE,
     LOADDATA_STATE,
@@ -65,6 +67,15 @@ enum {
     LEN_MIN_PASSWORD     = 4
 };
 
+// Default game values
+// -------------------
+// Screen
+const short defaultScreenWidth = 800;
+const short defaultScreenHeight = 600;
+// Sound
+const short defaultSfxVolume = 100;
+const short defaultMusicVolume = 60;
+
 extern char n_server, n_character;
 extern unsigned char state;
 extern std::string errorMessage;
diff --git a/src/openglgraphics.cpp b/src/openglgraphics.cpp
index f2406e38..51e99fa0 100644
--- a/src/openglgraphics.cpp
+++ b/src/openglgraphics.cpp
@@ -21,10 +21,18 @@
  *  $Id$
  */
 
+#include "main.h"
+
 #ifdef USE_OPENGL
 
+#ifndef GL_TEXTURE_RECTANGLE_ARB
+#define GL_TEXTURE_RECTANGLE_ARB 0x84F5
+#define GL_MAX_RECTANGLE_TEXTURE_SIZE_ARB 0x84F8
+#endif
+
 #include "openglgraphics.h"
 
+#include <cstring>
 #include <SDL.h>
 
 #ifdef __APPLE__
@@ -33,7 +41,6 @@
 
 #include <guichan/exception.hpp>
 #include <guichan/image.hpp>
-#include <guichan/opengl/openglimage.hpp>
 
 #include "log.h"
 
@@ -81,27 +88,79 @@ bool OpenGLGraphics::setVideoMode(int w, int h, int bpp, bool fs, bool hwaccel)
     logger->log("Using OpenGL %s double buffering.",
             (gotDoubleBuffer ? "with" : "without"));
 
+    char const *glExtensions = (char const *)glGetString(GL_EXTENSIONS);
+    int texSize;
+    bool rectTex = strstr(glExtensions, "GL_ARB_texture_rectangle");
+    if (rectTex)
+    {
+        Image::mTextureType = GL_TEXTURE_RECTANGLE_ARB;
+        glGetIntegerv(GL_MAX_RECTANGLE_TEXTURE_SIZE_ARB, &texSize);
+    }
+    else
+    {
+        Image::mTextureType = GL_TEXTURE_2D;
+        glGetIntegerv(GL_MAX_TEXTURE_SIZE, &texSize);
+    }
+    Image::mTextureSize = texSize;
+    logger->log("OpenGL texture size: %d pixels%s", Image::mTextureSize,
+                rectTex ? " (rectangle textures)" : "");
+
     return true;
 }
 
 bool OpenGLGraphics::drawImage(Image *image, int srcX, int srcY,
-        int dstX, int dstY, int width, int height)
+        int dstX, int dstY, int width, int height, bool useColor)
 {
     srcX += image->mBounds.x;
     srcY += image->mBounds.y;
 
-    // Find OpenGL texture coordinates
-    float texX1 = srcX / (float)image->mTexWidth;
-    float texY1 = srcY / (float)image->mTexHeight;
-    float texX2 = (srcX + width) / (float)image->mTexWidth;
-    float texY2 = (srcY + height) / (float)image->mTexHeight;
+    if (!useColor)
+    {
+        glColor4f(1.0f, 1.0f, 1.0f, image->mAlpha);
+    }
+
+    glBindTexture(Image::mTextureType, image->mGLImage);
 
-    glColor4f(1.0f, 1.0f, 1.0f, image->mAlpha);
-    glBindTexture(GL_TEXTURE_2D, image->mGLImage);
+    setTexturingAndBlending(true);
 
-    drawTexedQuad(dstX, dstY, width, height, texX1, texY1, texX2, texY2);
+    // Draw a textured quad.
+    glBegin(GL_QUADS);
 
-    glColor4ub(mColor.r, mColor.g, mColor.b, mColor.a);
+    if (Image::mTextureType == GL_TEXTURE_2D)
+    {
+        // Find OpenGL normalized texture coordinates.
+        float texX1 = srcX / (float)image->mTexWidth;
+        float texY1 = srcY / (float)image->mTexHeight;
+        float texX2 = (srcX + width) / (float)image->mTexWidth;
+        float texY2 = (srcY + height) / (float)image->mTexHeight;
+
+        glTexCoord2f(texX1, texY1);
+        glVertex2i(dstX, dstY);
+        glTexCoord2f(texX2, texY1);
+        glVertex2i(dstX + width, dstY);
+        glTexCoord2f(texX2, texY2);
+        glVertex2i(dstX + width, dstY + height);
+        glTexCoord2f(texX1, texY2);
+        glVertex2i(dstX, dstY + height);
+    }
+    else
+    {
+        glTexCoord2i(srcX, srcY);
+        glVertex2i(dstX, dstY);
+        glTexCoord2i(srcX + width, srcY);
+        glVertex2i(dstX + width, dstY);
+        glTexCoord2i(srcX + width, srcY + height);
+        glVertex2i(dstX + width, dstY + height);
+        glTexCoord2i(srcX, srcY + height);
+        glVertex2i(dstX, dstY + height);
+    }
+
+    glEnd();
+
+    if (!useColor)
+    {
+        glColor4ub(mColor.r, mColor.g, mColor.b, mColor.a);
+    }
 
     return true;
 }
@@ -227,33 +286,6 @@ void OpenGLGraphics::setColor(const gcn::Color& color)
     mColorAlpha = (color.a != 255);
 }
 
-void OpenGLGraphics::drawImage(const gcn::Image* image,
-                               int srcX, int srcY,
-                               int dstX, int dstY,
-                               int width, int height)
-{
-    const gcn::OpenGLImage* srcImage =
-        dynamic_cast<const gcn::OpenGLImage*>(image);
-
-    if (srcImage == NULL)
-    {
-        throw GCN_EXCEPTION("Trying to draw an image of unknown format, "
-                            "must be an SDLImage.");
-    }
-
-    // Find OpenGL texture coordinates
-    float texX1 = srcX / (float)srcImage->getTextureWidth();
-    float texY1 = srcY / (float)srcImage->getTextureHeight();
-    float texX2 = (srcX + width) / (float)srcImage->getTextureWidth();
-    float texY2 = (srcY + height) / (float)srcImage->getTextureHeight();
-
-    // Please dont look too closely at the next line, it is not pretty.
-    // It uses the image data as a pointer to a GLuint
-    glBindTexture(GL_TEXTURE_2D, srcImage->getTextureHandle());
-
-    drawTexedQuad(dstX, dstY, width, height, texX1, texY1, texX2, texY2);
-}
-
 void OpenGLGraphics::drawPoint(int x, int y)
 {
     setTexturingAndBlending(false);
@@ -295,9 +327,9 @@ void OpenGLGraphics::setTexturingAndBlending(bool enable)
 {
     if (enable) {
         if (!mTexture) {
-            glEnable(GL_TEXTURE_2D);
+            glEnable(Image::mTextureType);
             mTexture = true;
-        };
+        }
 
         if (!mAlpha)
         {
@@ -314,7 +346,7 @@ void OpenGLGraphics::setTexturingAndBlending(bool enable)
         }
 
         if (mTexture) {
-            glDisable(GL_TEXTURE_2D);
+            glDisable(Image::mTextureType);
             mTexture = false;
         }
     }
@@ -334,25 +366,4 @@ void OpenGLGraphics::drawRectangle(const gcn::Rectangle& rect, bool filled)
     glEnd();
 }
 
-void OpenGLGraphics::drawTexedQuad(int x, int y, int w, int h,
-        float texX1, float texY1, float texX2, float texY2)
-{
-    setTexturingAndBlending(true);
-
-    // Draw a textured quad
-    glBegin(GL_QUADS);
-    glTexCoord2f(texX1, texY1);
-    glVertex2i(x, y);
-
-    glTexCoord2f(texX2, texY1);
-    glVertex2i(x + w, y);
-
-    glTexCoord2f(texX2, texY2);
-    glVertex2i(x + w, y + h);
-
-    glTexCoord2f(texX1, texY2);
-    glVertex2i(x, y + h);
-    glEnd();
-}
-
 #endif // USE_OPENGL
diff --git a/src/openglgraphics.h b/src/openglgraphics.h
index c61ae66c..ee5bc1e1 100644
--- a/src/openglgraphics.h
+++ b/src/openglgraphics.h
@@ -38,7 +38,8 @@ class OpenGLGraphics : public Graphics
         bool drawImage(Image *image,
                        int srcX, int srcY,
                        int dstX, int dstY,
-                       int width, int height);
+                       int width, int height,
+                       bool useColor);
 
         void updateScreen();
 
@@ -50,11 +51,6 @@ class OpenGLGraphics : public Graphics
 
         void setColor(const gcn::Color &color);
 
-        void drawImage(const gcn::Image* image,
-                       int srcX, int srcY,
-                       int dstX, int dstY,
-                       int width, int height);
-
         void drawPoint(int x, int y);
 
         void drawLine(int x1, int y1, int x2, int y2);
@@ -74,8 +70,6 @@ class OpenGLGraphics : public Graphics
 
     protected:
         void setTexturingAndBlending(bool enable);
-        void drawTexedQuad(int x, int y, int w, int h,
-                           float texX1, float texY1, float texX2, float texY2);
 
     private:
         bool mAlpha, mTexture;
diff --git a/src/resources/image.cpp b/src/resources/image.cpp
index ad280eeb..995e34b0 100644
--- a/src/resources/image.cpp
+++ b/src/resources/image.cpp
@@ -29,6 +29,8 @@
 
 #ifdef USE_OPENGL
 bool Image::mUseOpenGL = false;
+int Image::mTextureType = 0;
+int Image::mTextureSize = 0;
 #endif
 
 Image::Image(const std::string &idPath, SDL_Surface *image):
@@ -89,23 +91,21 @@ Image* Image::load(void *buffer, unsigned int bufferSize,
         return NULL;
     }
 
-    // Determine 32-bit masks based on byte order
-    Uint32 rmask, gmask, bmask, amask;
-#if SDL_BYTEORDER == SDL_BIG_ENDIAN
-    rmask = 0xff000000;
-    gmask = 0x00ff0000;
-    bmask = 0x0000ff00;
-    amask = 0x000000ff;
-#else
-    rmask = 0x000000ff;
-    gmask = 0x0000ff00;
-    bmask = 0x00ff0000;
-    amask = 0xff000000;
-#endif
+    Image *image = load(tmpImage, idPath);
+
+    SDL_FreeSurface(tmpImage);
 
+    return image;
+}
+
+Image *Image::load(SDL_Surface *tmpImage, std::string const &idPath)
+{
 #ifdef USE_OPENGL
     if (mUseOpenGL)
     {
+        // Flush current error flag.
+        glGetError();
+
         int width = tmpImage->w;
         int height = tmpImage->h;
         int realWidth = powerOfTwo(width);
@@ -120,6 +120,20 @@ Image* Image::load(void *buffer, unsigned int bufferSize,
         // Make sure the alpha channel is not used, but copied to destination
         SDL_SetAlpha(tmpImage, 0, SDL_ALPHA_OPAQUE);
 
+        // Determine 32-bit masks based on byte order
+        Uint32 rmask, gmask, bmask, amask;
+#if SDL_BYTEORDER == SDL_BIG_ENDIAN
+        rmask = 0xff000000;
+        gmask = 0x00ff0000;
+        bmask = 0x0000ff00;
+        amask = 0x000000ff;
+#else
+        rmask = 0x000000ff;
+        gmask = 0x0000ff00;
+        bmask = 0x00ff0000;
+        amask = 0xff000000;
+#endif
+
         SDL_Surface *oldImage = tmpImage;
         tmpImage = SDL_CreateRGBSurface(SDL_SWSURFACE, realWidth, realHeight,
             32, rmask, gmask, bmask, amask);
@@ -130,25 +144,24 @@ Image* Image::load(void *buffer, unsigned int bufferSize,
         }
 
         SDL_BlitSurface(oldImage, NULL, tmpImage, NULL);
-        SDL_FreeSurface(oldImage);
 
         GLuint texture;
         glGenTextures(1, &texture);
-        glBindTexture(GL_TEXTURE_2D, texture);
+        glBindTexture(mTextureType, texture);
 
         if (SDL_MUSTLOCK(tmpImage)) {
             SDL_LockSurface(tmpImage);
         }
 
         glTexImage2D(
-                GL_TEXTURE_2D, 0, 4,
+                mTextureType, 0, 4,
                 tmpImage->w, tmpImage->h,
                 0, GL_RGBA, GL_UNSIGNED_BYTE,
                 tmpImage->pixels);
 
         glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
-        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+        glTexParameteri(mTextureType, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+        glTexParameteri(mTextureType, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
 
         if (SDL_MUSTLOCK(tmpImage)) {
             SDL_UnlockSurface(tmpImage);
@@ -219,7 +232,6 @@ Image* Image::load(void *buffer, unsigned int bufferSize,
     else {
         image = SDL_DisplayFormat(tmpImage);
     }
-    SDL_FreeSurface(tmpImage);
 
     if (!image) {
         logger->log("Error: Image convert failed.");
@@ -289,12 +301,20 @@ Image::setLoadAsOpenGL(bool useOpenGL)
 int
 Image::powerOfTwo(int input)
 {
-    int value = 1;
-    while (value < input && value < 1024)
+    int value;
+    if (mTextureType == GL_TEXTURE_2D)
+    {
+        value = 1;
+        while (value < input && value < mTextureSize)
+        {
+            value <<= 1;
+        }
+    }
+    else
     {
-        value <<= 1;
+        value = input;
     }
-    return value;
+    return value >= mTextureSize ? mTextureSize : value;
 }
 #endif
 
diff --git a/src/resources/image.h b/src/resources/image.h
index 23715ecb..34515dda 100644
--- a/src/resources/image.h
+++ b/src/resources/image.h
@@ -24,6 +24,8 @@
 #ifndef _TMW_IMAGE_H
 #define _TMW_IMAGE_H
 
+#include "../main.h"
+
 #include <SDL.h>
 #ifdef USE_OPENGL
 
@@ -68,6 +70,11 @@ class Image : public Resource
         static Image*
         load(void* buffer, unsigned int bufferSize, const std::string &idPath);
 
+        /**
+         * Loads an image from an SDL surface.
+         */
+        static Image *load(SDL_Surface *, std::string const &idPath);
+
         /**
          * Frees the resources created by SDL.
          */
@@ -141,6 +148,8 @@ class Image : public Resource
         int mTexWidth, mTexHeight;
 
         static bool mUseOpenGL;
+        static int mTextureType;
+        static int mTextureSize;
 #endif
         SDL_Surface *mImage;
         float mAlpha;
diff --git a/src/resources/imageloader.cpp b/src/resources/imageloader.cpp
new file mode 100644
index 00000000..81a5cf63
--- /dev/null
+++ b/src/resources/imageloader.cpp
@@ -0,0 +1,99 @@
+/*
+ *  The Mana World
+ *  Copyright 2007 The Mana World Development Team
+ *
+ *  This file is part of The Mana World.
+ *
+ *  The Mana World is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  any later version.
+ *
+ *  The Mana World 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 The Mana World; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ *  $Id: imageloader.cpp 3515 2007-08-25 16:56:52Z gmelquio $
+ */
+
+#include <cassert>
+#include <string>
+#include <guichan/color.hpp>
+#include <guichan/sdl/sdlpixel.hpp>
+
+#include "imageloader.h"
+
+#include "image.h"
+#include "resourcemanager.h"
+
+ProxyImage::ProxyImage(SDL_Surface *s):
+    mImage(NULL), mSDLImage(s)
+{
+}
+
+ProxyImage::~ProxyImage()
+{
+    free();
+}
+
+void ProxyImage::free()
+{
+    if (mSDLImage)
+    {
+        SDL_FreeSurface(mSDLImage);
+        mSDLImage = NULL;
+    }
+    else if (mImage)
+    {
+        delete mImage;
+        mImage = NULL;
+    }
+}
+
+int ProxyImage::getWidth() const
+{
+    return mSDLImage ? mSDLImage->w : mImage->getWidth();
+}
+
+int ProxyImage::getHeight() const
+{
+    return mSDLImage ? mSDLImage->h : mImage->getHeight();
+}
+
+gcn::Color ProxyImage::getPixel(int x, int y)
+{
+    assert(mSDLImage);
+    return gcn::SDLgetPixel(mSDLImage, x, y);
+}
+
+void ProxyImage::putPixel(int x, int y, gcn::Color const &color)
+{
+    assert(mSDLImage);
+    gcn::SDLputPixel(mSDLImage, x, y, color);
+}
+
+void ProxyImage::convertToDisplayFormat()
+{
+    assert(mSDLImage);
+    /* The picture is most probably full of the pink pixels Guichan uses for
+       transparency, as this function will only be called when setting an image
+       font. Get rid of them. */
+    SDL_SetColorKey(mSDLImage, SDL_SRCCOLORKEY,
+                    SDL_MapRGB(mSDLImage->format, 255, 0, 255));
+    mImage = ::Image::load(mSDLImage, std::string());
+    SDL_FreeSurface(mSDLImage);
+    mSDLImage = NULL;
+}
+
+gcn::Image *ImageLoader::load(std::string const &filename, bool convert)
+{
+    ResourceManager *resman = ResourceManager::getInstance();
+    ProxyImage *i = new ProxyImage(resman->loadSDLSurface(filename));
+    if (convert) i->convertToDisplayFormat();
+    return i;
+}
diff --git a/src/resources/imageloader.h b/src/resources/imageloader.h
new file mode 100644
index 00000000..89f38eda
--- /dev/null
+++ b/src/resources/imageloader.h
@@ -0,0 +1,69 @@
+/*
+ *  The Mana World
+ *  Copyright 2007 The Mana World Development Team
+ *
+ *  This file is part of The Mana World.
+ *
+ *  The Mana World is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  any later version.
+ *
+ *  The Mana World 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 The Mana World; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ *  $Id: imageloader.h 3515 2007-08-25 16:56:52Z gmelquio $
+ */
+
+#ifndef _TMW_IMAGELOADER_H
+#define _TMW_IMAGELOADER_H
+
+#include <string>
+
+#include <guichan/image.hpp>
+#include <guichan/imageloader.hpp>
+
+class Image;
+struct SDL_Surface;
+
+class ProxyImage : public gcn::Image
+{
+    public:
+        ProxyImage(SDL_Surface *);
+        ~ProxyImage();
+        void free();
+        int getWidth() const;
+        int getHeight() const;
+        gcn::Color getPixel(int x, int y);
+        void putPixel(int x, int y, gcn::Color const &color);
+        void convertToDisplayFormat();
+
+        /**
+         * Gets the image handled by this proxy.
+         */
+        ::Image *getImage() const
+        { return mImage; }
+
+    private:
+        ::Image *mImage; /**< The real image. */
+
+        /**
+         * An SDL surface kept around until Guichan is done reading pixels from
+         * an OpenGL texture.
+         */
+        SDL_Surface *mSDLImage;
+};
+
+class ImageLoader : public gcn::ImageLoader
+{
+    public:
+        gcn::Image *load(std::string const &filename, bool convertToDisplayFormat);
+};
+
+#endif
diff --git a/src/resources/iteminfo.cpp b/src/resources/iteminfo.cpp
index c2be5396..b5b25ac0 100644
--- a/src/resources/iteminfo.cpp
+++ b/src/resources/iteminfo.cpp
@@ -18,6 +18,7 @@
  *  along with The Mana World; if not, write to the Free Software
  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
+ *  $Id$
  */
 
 #include "iteminfo.h"
diff --git a/src/resources/openglsdlimageloader.cpp b/src/resources/openglsdlimageloader.cpp
deleted file mode 100644
index 5915fb49..00000000
--- a/src/resources/openglsdlimageloader.cpp
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- *  The Mana World
- *  Copyright 2004 The Mana World Development Team
- *
- *  This file is part of The Mana World.
- *
- *  The Mana World is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  any later version.
- *
- *  The Mana World 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 The Mana World; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- *  $Id: sdlimageloader.cpp 2121 2006-01-31 02:55:26Z der_doener $
- */
-
-#ifdef USE_OPENGL
-
-#include "openglsdlimageloader.h"
-
-#include <string>
-
-#include "resourcemanager.h"
-
-SDL_Surface*
-OpenGLSDLImageLoader::loadSDLSurface(const std::string &filename)
-{
-    ResourceManager *resman = ResourceManager::getInstance();
-    return resman->loadSDLSurface(filename);
-}
-
-#endif
diff --git a/src/resources/openglsdlimageloader.h b/src/resources/openglsdlimageloader.h
deleted file mode 100644
index b79dde15..00000000
--- a/src/resources/openglsdlimageloader.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- *  The Mana World
- *  Copyright 2004 The Mana World Development Team
- *
- *  This file is part of The Mana World.
- *
- *  The Mana World is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  any later version.
- *
- *  The Mana World 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 The Mana World; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- *  $Id: sdlimageloader.h 1724 2005-09-12 22:15:35Z der_doener $
- */
-
-#ifndef _TMW_OPENGLSDLIMAGELOADER_H
-#define _TMW_OPENGLSDLIMAGELOADER_H
-
-#include <iosfwd>
-
-#include <guichan/opengl/openglsdlimageloader.hpp>
-
-class OpenGLSDLImageLoader : public gcn::OpenGLSDLImageLoader
-{
-    protected:
-        SDL_Surface*
-        loadSDLSurface(const std::string &filename);
-};
-
-#endif
diff --git a/src/resources/sdlimageloader.cpp b/src/resources/sdlimageloader.cpp
deleted file mode 100644
index ae4f4dcb..00000000
--- a/src/resources/sdlimageloader.cpp
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- *  The Mana World
- *  Copyright 2004 The Mana World Development Team
- *
- *  This file is part of The Mana World.
- *
- *  The Mana World is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  any later version.
- *
- *  The Mana World 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 The Mana World; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- *  $Id$
- */
-
-#include "sdlimageloader.h"
-
-#include <string>
-
-#include "resourcemanager.h"
-
-SDL_Surface* SDLImageLoader::loadSDLSurface(const std::string& filename)
-{
-    ResourceManager *resman = ResourceManager::getInstance();
-    return resman->loadSDLSurface(filename);
-}
diff --git a/src/resources/sdlimageloader.h b/src/resources/sdlimageloader.h
deleted file mode 100644
index 50b1d4f1..00000000
--- a/src/resources/sdlimageloader.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- *  The Mana World
- *  Copyright 2004 The Mana World Development Team
- *
- *  This file is part of The Mana World.
- *
- *  The Mana World is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  any later version.
- *
- *  The Mana World 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 The Mana World; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- *  $Id$
- */
-
-#ifndef _TMW_SDLIMAGELOADER_H
-#define _TMW_SDLIMAGELOADER_H
-
-#include <iosfwd>
-
-#include <guichan/sdl/sdlimageloader.hpp>
-
-class SDLImageLoader : public gcn::SDLImageLoader
-{
-    protected:
-        SDL_Surface* loadSDLSurface(const std::string& filename);
-};
-
-#endif
diff --git a/src/utils/minmax.h b/src/utils/minmax.h
index ea6ad9e0..427c5da7 100644
--- a/src/utils/minmax.h
+++ b/src/utils/minmax.h
@@ -21,6 +21,8 @@
  *  $Id$
  */
 
+#include <cstdlib>
+
 /**
  * Returns a random numeric value that is larger than or equal min and smaller
  * than max
-- 
cgit v1.2.3-70-g09d2