074140aacade8777cb746dc3c525ce4e089c16f0
[supertux.git] / src / unison / include / unison / video / Surface.hpp
1 //          Copyright Timothy Goya 2007.
2 // Distributed under the Boost Software License, Version 1.0.
3 //    (See accompanying file LICENSE_1_0.txt or copy at
4 //          http://www.boost.org/LICENSE_1_0.txt)
5
6 #ifndef UNISON_VIDEO_SURFACE_HPP
7 #define UNISON_VIDEO_SURFACE_HPP
8
9 #include <unison/video/Blittable.hpp>
10 #include <unison/video/RenderOptions.hpp>
11
12 #include <string>
13 #include <istream>
14 #include <assert.h>
15
16 namespace Unison
17 {
18    namespace Video
19    {
20       class Color;
21       class Rect;
22       class Texture;
23       /// An image that is optimized for easy manipulation
24       class Surface : public Blittable
25       {
26          public:
27             /// Default constructor
28             Surface();
29
30             /// Create a Surface from an input stream
31             /// \param[in] src The input stream
32             Surface(std::istream &stream);
33
34             /// Create a Surface from an input stream
35             /// \param[in] src The input stream
36             /// \param[in] colorkey The colorkey used by the file
37             Surface(std::istream &stream, const Color &colorkey);
38
39             /// Opens image file indicated by filename
40             /// \param[in] filename The filename of the image file
41             Surface(const std::string &filename);
42
43             /// Opens image file indicated by filename and use the specified color key
44             /// \param[in] filename The filename of the image file
45             /// \param[in] colorkey The colorkey used by the file
46             Surface(const std::string &filename, const Color &colorkey);
47
48             /// Creates Surface of indicated dimensions
49             /// \param[in] size The size of the desired surface
50             Surface(const Area &size);
51
52             /// Copy constructor
53             /// \param[in] rhs The source surface
54             Surface(const Surface &rhs);
55
56             /// Destructor
57             ~Surface();
58
59             /// Assignment operator
60             /// \param[in] rhs The source surface
61             Surface &operator =(const Surface &rhs);
62
63             /// Saves the surface to file
64             /// \param[in] filename The destination filename
65             void save(const std::string &filename) const;
66
67             /// Retrieves the window's size
68             /// \return The size of the surface
69             Area get_size() const
70             {
71                return pixels ? pixels->size : Area();
72             }
73
74             /// Retrieves a pixel at the specified coordinates
75             /// \param[in] pos The position of the pixel to retrieve
76             /// \return The pixel at the specified position
77             Color &get_pixel(const Point &pos)
78             {
79                cow();
80                assert(pixels);
81                return pixels->buffer[pos.y * pixels->size.x + pos.x];
82             }
83
84             /// Retrieves the pixel color at the specified coordinates
85             /// \param[in] x The x position of the pixel to retrieve
86             /// \param[in] y The y position of the pixel to retrieve
87             /// \return The color of the pixel at the specified position
88             Color& get_pixel(int x, int y)
89             {
90                cow();
91                assert(pixels);
92                return pixels->buffer[y * pixels->size.x + x];
93             }
94
95             /// Retrieves the pixel color at the specified coordinates
96             /// \param[in] pos The position of the pixel to retrieve
97             /// \return The color of the pixel at the specified position
98             Color get_pixel(const Point &pos) const
99             {
100                assert(pixels);
101                return pixels->buffer[pos.y * pixels->size.x + pos.x];
102             }
103
104             /// Retrieves the pixel color at the specified coordinates
105             /// \param[in] x The x position of the pixel to retrieve
106             /// \param[in] y The y position of the pixel to retrieve
107             /// \return The color of the pixel at the specified position
108             Color get_pixel(int x, int y) const
109             {
110                assert(pixels);
111                return pixels->buffer[y * pixels->size.x + x];
112             }
113
114             /// Acquire the pixel color buffer
115             /// \return the pixel color buffer
116             Color *get_pixels()
117             {
118                cow();
119                assert(pixels);
120                return pixels->buffer;
121             }
122
123             /// Acquire the pixel color buffer
124             /// \return the pixel color buffer
125             const Color *get_pixels() const
126             {
127                assert(pixels);
128                return pixels->buffer;
129             }
130
131             /// Does a surface-to-surface blit
132             /// \param[in] src The source surface
133             /// \param[in] dst_pos The position to blit to
134             /// \param[in] src_rect The part of the source surface to blit from
135             /// \param[in] options Extra blit options
136             void blit(const Surface &src, const Point &dst_pos = Point(), const Rect &src_rect = Rect(), const RenderOptions &options = RenderOptions());
137
138             /// Does a texture-to-surface blit
139             /// \param[in] src The source texture
140             /// \param[in] dst_pos The position to blit to
141             /// \param[in] src_rect The part of the source texture to blit from
142             /// \param[in] options Extra blit options
143             void blit(const Texture &src, const Point &dst_pos = Point(), const Rect &src_rect = Rect(), const RenderOptions &options = RenderOptions());
144
145             /// Fills a portion of the image with the given color
146             /// \param[in] color The color
147             /// \param[in] rect The portion to fill
148             void fill(const Color &color, const Rect &rect = Rect());
149
150             /// Fills and alpha blend a portion of the image with the given color
151             /// \param[in] color The color
152             /// \param[in] rect The portion to fill
153             void fill_blend(const Color &color, const Rect &rect = Rect());
154
155             /// Scale the surface by a factor of (numerator / denominator)
156             /// \param[in] numerator The numerator of the scale factor
157             /// \param[in] denominator The denominator of the scale factor
158             /// \return The scaled surface
159             Surface scale(unsigned int numerator, unsigned int denominator) const;
160
161             /// Flip the surface horizontally
162             /// \return The flipped surface
163             Surface h_flip() const;
164
165             /// Flip the surface vertically
166             /// \return The flipped surface
167             Surface v_flip() const;
168
169             /// Modulate the image with a color
170             /// \return The modulated surface
171             Surface modulate(const Color &color) const;
172
173             /// Modulate the image with an alpha
174             /// \return The modulated surface
175             Surface modulate(unsigned char alpha) const;
176          private:
177             /// Copy on Write
178             void cow();
179
180             class PixelBuffer
181             {
182                public:
183                   PixelBuffer(Area size)
184                    : buffer(0),
185                      size(size),
186                      refcount(1)
187                   {
188                      if(size != Area())
189                      {
190                         buffer = new Color[size.x * size.y];
191                      }
192                   }
193
194                   ~PixelBuffer()
195                   {
196                      delete buffer;
197                   }
198
199                   void ref()
200                   {
201                      refcount++;
202                   }
203
204                   void unref()
205                   {
206                      assert(refcount > 0);
207                      refcount--;
208                      if(refcount == 0)
209                      {
210                         delete this;
211                      }
212                   }
213
214                   Color *buffer;
215                   Area size;
216                   int refcount;
217             };
218
219             /// The pixels
220             PixelBuffer *pixels;
221       };
222
223       /// A section of a surface
224       class SurfaceSection
225       {
226          public:
227             /// The image
228             Surface image;
229
230             /// The clip rectangle
231             Rect clip_rect;
232
233             /// Create a section from an image and a rectangle
234             /// \param[in] image The image
235             /// \param[in] rect The clip rectangle
236             SurfaceSection(const Surface &image = Surface(), const Rect &clip_rect = Rect()) :
237                image(image),
238                clip_rect(clip_rect)
239             {
240             }
241       };
242    }
243 }
244
245 #endif