Massive copyright update. I'm sorry if I'm crediting Matze for something he didn...
[supertux.git] / src / video / surface.cpp
1 //  $Id$
2 //
3 //  SuperTux
4 //  Copyright (C) 2006 Matthias Braun <matze@braunis.de>
5 //
6 //  This program is free software; you can redistribute it and/or
7 //  modify it under the terms of the GNU General Public License
8 //  as published by the Free Software Foundation; either version 2
9 //  of the License, or (at your option) any later version.
10 //
11 //  This program is distributed in the hope that it will be useful,
12 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
13 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 //  GNU General Public License for more details.
15 //
16 //  You should have received a copy of the GNU General Public License
17 //  along with this program; if not, write to the Free Software
18 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19
20 #include <config.h>
21
22 #include <cassert>
23 #include <iostream>
24 #include <algorithm>
25 #include <stdexcept>
26 #include <sstream>
27 #include <math.h>
28
29 #include <SDL.h>
30 #include <SDL_image.h>
31
32 #include "gameconfig.hpp"
33 #include "physfs/physfs_sdl.hpp"
34 #include "video/surface.hpp"
35 #include "video/screen.hpp"
36 #include "image_texture.hpp"
37 #include "texture_manager.hpp"
38
39 Surface::Surface(const std::string& file)
40 {
41   texture = texture_manager->get(file);
42   texture->ref();
43   uv_left = 0;
44   uv_top = 0;
45   uv_right = texture->get_uv_right();
46   uv_bottom = texture->get_uv_bottom();
47
48   width = texture->get_image_width();
49   height = texture->get_image_height();
50 }
51
52 Surface::Surface(const std::string& file, int x, int y, int w, int h)
53 {
54   texture = texture_manager->get(file);
55   texture->ref();
56
57   float tex_w = static_cast<float> (texture->get_width());
58   float tex_h = static_cast<float> (texture->get_height());
59   uv_left = static_cast<float>(x) / tex_w;
60   uv_top = static_cast<float>(y) / tex_h;
61   uv_right = static_cast<float>(x+w) / tex_w;
62   uv_bottom = static_cast<float>(y+h) / tex_h;
63
64   width = w;
65   height = h;
66 }
67
68 Surface::Surface(const Surface& other)
69 {
70   texture = other.texture;
71   texture->ref();
72
73   uv_left = other.uv_left;
74   uv_top = other.uv_top;
75   uv_right = other.uv_right;
76   uv_bottom = other.uv_bottom;
77   width = other.width;
78   height = other.height;
79 }
80
81 const Surface&
82 Surface::operator= (const Surface& other)
83 {
84   other.texture->ref();
85   texture->unref();
86   texture = other.texture;
87
88   uv_left = other.uv_left;
89   uv_top = other.uv_top;
90   uv_right = other.uv_right;
91   uv_bottom = other.uv_bottom;
92   width = other.width;
93   height = other.height;
94
95   return *this;
96 }
97
98 Surface::~Surface()
99 {
100   texture->unref();
101 }
102
103 void
104 Surface::hflip()
105 {
106   std::swap(uv_left, uv_right);
107 }
108
109 static inline void intern_draw(float left, float top, float right, float bottom,                               float uv_left, float uv_top,
110                                float uv_right, float uv_bottom,
111                                DrawingEffect effect)
112 {
113   if(effect & HORIZONTAL_FLIP)
114     std::swap(uv_left, uv_right);
115   if(effect & VERTICAL_FLIP) {
116     std::swap(uv_top, uv_bottom);
117   }
118   
119   glBegin(GL_QUADS);
120   glTexCoord2f(uv_left, uv_top);
121   glVertex2f(left, top);
122   
123   glTexCoord2f(uv_right, uv_top);
124   glVertex2f(right, top);
125
126   glTexCoord2f(uv_right, uv_bottom);
127   glVertex2f(right, bottom);
128
129   glTexCoord2f(uv_left, uv_bottom);
130   glVertex2f(left, bottom);
131   glEnd();
132 }
133
134 void
135 Surface::draw(float x, float y, float alpha, DrawingEffect effect) const
136 {
137   glColor4f(1.0f, 1.0f, 1.0f, alpha);
138   glBindTexture(GL_TEXTURE_2D, texture->get_handle());
139
140   intern_draw(x, y,
141               x + width, y + height,
142               uv_left, uv_top, uv_right, uv_bottom, effect);
143 }
144
145 void
146 Surface::draw_part(float src_x, float src_y, float dst_x, float dst_y,
147                    float width, float height, float alpha,
148                    DrawingEffect effect) const
149 {
150   float uv_width = uv_right - uv_left;
151   float uv_height = uv_bottom - uv_top;
152   
153   float uv_left = this->uv_left + (uv_width * src_x) / this->width;
154   float uv_top = this->uv_top + (uv_height * src_y) / this->height;
155   float uv_right = this->uv_left + (uv_width * (src_x + width)) / this->width;
156   float uv_bottom = this->uv_top + (uv_height * (src_y + height)) / this->height;
157   
158   glColor4f(1.0f, 1.0f, 1.0f, alpha);
159   glBindTexture(GL_TEXTURE_2D, texture->get_handle());  
160   
161   intern_draw(dst_x, dst_y,
162               dst_x + width, dst_y + height,
163               uv_left, uv_top, uv_right, uv_bottom, effect);
164 }
165