* Use overloading in Lisp and Writer
[supertux.git] / src / video / surface.hpp
index bd0da7c..d90494b 100644 (file)
@@ -1,7 +1,7 @@
-//  $Id: surface.h 2175 2004-11-24 19:02:49Z sik0fewl $
-// 
+//  $Id$
+//
 //  SuperTux
-//  Copyright (C) 2004 Tobias Glaesser <tobi.web@gmx.de>
+//  Copyright (C) 2006 Matthias Braun <matze@braunis.de>
 //
 //  This program is free software; you can redistribute it and/or
 //  modify it under the terms of the GNU General Public License
 //  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.
-#ifndef SUPERTUX_TEXTURE_H
-#define SUPERTUX_TEXTURE_H
+#ifndef __SURFACE_HPP__
+#define __SURFACE_HPP__
 
-#include <string>
-#include <list>
+#include <config.h>
 
+#include <string>
 #include <SDL.h>
-#include <GL/gl.h>
-
 #include "math/vector.hpp"
-#include "video/screen.hpp"
-
-void apply_filter_to_surface(SDL_Surface *surface, int filter, int value);
-SDL_Surface* sdl_surface_from_sdl_surface(SDL_Surface* sdl_surf);
-SDL_Surface* sdl_surface_from_nothing();
-
-class SurfaceImpl;
-class SurfaceOpenGL;
-class DrawingContext;
-  
-/// bitset for drawing effects
-enum {
-  /** Don't apply anything */
-  NONE_EFFECT       = 0x0000,
-  /** Draw the Surface upside down */
-  VERTICAL_FLIP     = 0x0001,
-  /** Draw the Surface from left to down */
-  HORIZONTAL_FLIP   = 0x0002,
-  /** Draw the Surface with alpha equal to 128 */
-  SEMI_TRANSPARENT  = 0x0004
-};
+#include "texture.hpp"
+#include "video_systems.hpp"
 
-/// types of filters
-enum {
-  HORIZONTAL_FLIP_FILTER,
-  MASK_FILTER,
-  NONE_FILTER
-};
-
-/** This class holds all the data necessary to construct a surface */
-class SurfaceData
+/**
+ * A rectangular image.
+ * The class basically holds a reference to a texture with additional UV
+ * coordinates that specify a rectangular area on this texture
+ */
+class Surface
 {
-public:
-  enum ConstructorType { LOAD, LOAD_PART, SURFACE, GRADIENT };
-  ConstructorType type;
-  SDL_Surface* surface;
-  std::string file;
-  
-  struct Filter { int type; Color color; };
-  std::vector<Filter> applied_filters;
-  
-  bool use_alpha;
+private:
+  Texture* texture;
+  void *surface_data;
   int x;
   int y;
   int w;
   int h;
-  Color top_gradient;
-  Color bottom_gradient;
-  
-  SurfaceData(SDL_Surface* surf, bool use_alpha_);
-  SurfaceData(const std::string& file_, bool use_alpha_);
-  SurfaceData(const std::string& file_, int x_, int y_, int w_, int h_, bool use_alpha_);
-  SurfaceData(Color top_gradient_, Color bottom_gradient_, int w_, int h_);
-  ~SurfaceData();
-  
-  SurfaceOpenGL* create_SurfaceOpenGL();
-  SurfaceImpl* create();
-};
-
+  bool flipx;
 
-/** Container class that holds a surface, necessary so that we can
- *  switch Surface implementations (OpenGL, SDL) on the fly
- */
-class Surface
-{
 public:
-  SurfaceImpl* impl;
-  SurfaceData data;
-  int w;
-  int h;
-  
-  typedef std::list<Surface*> Surfaces;
-  static Surfaces surfaces;
-public:
-  static void reload_all();
-  static void debug_check();
-  
-  Surface(SDL_Surface* surf, bool use_alpha);
-  Surface(const std::string& file, bool use_alpha);
-  Surface(const std::string& file, int x, int y, int w, int h, bool use_alpha);
-  Surface(Color top_gradient, Color bottom_gradient, int w_, int h_);
-  ~Surface();
-  
-  /** Reload the surface, which is necesarry in case of a mode swich */
-  void reload();
-  
-  void apply_filter(int filter, Color color = Color(0,0,0));
-};
+  Surface(const std::string& file) :
+    texture(texture_manager->get(file)),
+    x(0), y(0), w(0), h(0),
+    flipx(false)
+  {
+    texture->ref();
+    w = texture->get_image_width();
+    h = texture->get_image_height();
+    surface_data = new_surface_data(*this);
+  }
 
-/** Surface implementation, all implementation have to inherit from
-    this class */
-class SurfaceImpl
-{
-protected:
-  SDL_Surface* sdl_surface;
-  
-public:
-  int w;
-  int h;
-  
-public:
-  SurfaceImpl();
-  virtual ~SurfaceImpl();
-  
-  /** Return 0 on success, -2 if surface needs to be reloaded */
-  virtual int draw(float x, float y, Uint8 alpha, Uint32 effect = NONE_EFFECT) = 0;
-  virtual int draw_part(float sx, float sy, float x, float y, float w, float h,  Uint8 alpha, Uint32 effect = NONE_EFFECT) = 0;
-  virtual int draw_stretched(float x, float y, int w, int h, Uint8 alpha, Uint32 effect = NONE_EFFECT) = 0;
-  
-  
-  SDL_Surface* get_sdl_surface() const; // @evil@ try to avoid this function
-  
-  virtual void apply_filter(int filter, Color color = Color(0,0,0)) = 0;
-};
+  Surface(const std::string& file, int x, int y, int w, int h) :
+    texture(texture_manager->get(file)),
+    x(x), y(y), w(w), h(h),
+    flipx(false)
+  {
+    texture->ref();
+    surface_data = new_surface_data(*this);
+  }
 
-class SurfaceOpenGL : public SurfaceImpl
-{
-public:
-  GLuint gl_texture;
-  
-public:
-  SurfaceOpenGL(SDL_Surface* surf);
-  SurfaceOpenGL(const std::string& file);
-  SurfaceOpenGL(const std::string& file, int x, int y, int w, int h);
-  SurfaceOpenGL(Color top_gradient, Color bottom_gradient, int w, int h);
-  
-  virtual ~SurfaceOpenGL();
-  
-  int draw(float x, float y, Uint8 alpha, Uint32 effect = NONE_EFFECT);
-  int draw_part(float sx, float sy, float x, float y, float w, float h,  Uint8 alpha, Uint32 effect = NONE_EFFECT);
-  int draw_stretched(float x, float y, int w, int h, Uint8 alpha, Uint32 effect = NONE_EFFECT);
-  
-  void apply_filter(int filter, Color color);
-  
-private:
-  void create_gl(SDL_Surface * surf, GLuint * tex);
+  Surface(const Surface& other) :
+    texture(other.texture),
+    x(other.x), y(other.y),
+    w(other.w), h(other.h),
+    flipx(false)
+  {
+    texture->ref();
+    surface_data = new_surface_data(*this);
+  }
+
+  ~Surface()
+  {
+    free_surface_data(surface_data);
+    texture->unref();
+  }
+
+  /** flip the surface horizontally */
+  void hflip()
+  {
+    flipx = !flipx;
+  }
+
+  bool get_flipx() const
+  {
+    return flipx;
+  }
+
+  const Surface& operator= (const Surface& other)
+  {
+    other.texture->ref();
+    texture->unref();
+    texture = other.texture;
+    x = other.x;
+    y = other.y;
+    w = other.w;
+    h = other.h;
+    return *this;
+  }
+
+  Texture *get_texture() const
+  {
+    return texture;
+  }
+
+  void *get_surface_data() const
+  {
+    return surface_data;
+  }
+
+  int get_x() const
+  {
+    return x;
+  }
+
+  int get_y() const
+  {
+    return y;
+  }
+
+  int get_width() const
+  {
+    return w;
+  }
+
+  int get_height() const
+  {
+    return h;
+  }
+
+  Vector get_position() const
+  { return Vector(get_x(), get_y()); }
+
+  /**
+   * returns a vector containing width and height
+   */
+  Vector get_size() const
+  { return Vector(get_width(), get_height()); }
 };
 
 #endif