cpp-sdl2
C++ header-only SDL2 wrapper
surface.hpp
Go to the documentation of this file.
1 #pragma once
2 
3 #include <string>
4 #include <utility>
5 
6 #include <SDL_surface.h>
7 
8 #ifdef CPP_SDL2_ENABLE_SDL_IMAGE
9 #include <SDL_image.h>
10 #endif
11 
12 #include "color.hpp"
13 #include "exception.hpp"
14 #include "pixel.hpp"
15 #include "rect.hpp"
16 #include "vec2.hpp"
17 
18 namespace sdl
19 {
21 class Surface
22 {
23 public:
25  class Lock
26  {
27  friend class Surface;
28 
29  public:
31  Pixel at(Vec2i const& pos) const { return at(pos.x, pos.y); }
33  Pixel at(size_t x, size_t y) const
34  {
35  return Pixel{
36  static_cast<Uint8*>(surface_->pixels) + (y * surface_->pitch)
37  + (x * surface_->format->BytesPerPixel),
38  *surface_->format};
39  }
40 
42  Pixel operator[](Vec2i const& pos) const { return at(pos.x, pos.y); }
43 
45  void* raw_array() const { return surface_->pixels; }
46 
48  ~Lock() { SDL_UnlockSurface(surface_); }
49 
50  private:
52  constexpr Lock(SDL_Surface& surface_) : surface_{&surface_} {}
53 
55  SDL_Surface* surface_;
56  };
57 
59  explicit Surface(SDL_Surface* surface) : surface_{surface} {}
60 
61  Surface(Surface&& other) noexcept { *this = std::move(other); }
62 
63  Surface& operator=(Surface&& other) noexcept
64  {
65  if (surface_ != other.surface_)
66  {
67  SDL_FreeSurface(surface_);
68  surface_ = other.surface_;
69  other.surface_ = nullptr;
70  }
71  return *this;
72  }
73 
76  Uint32 flags,
77  int w,
78  int h,
79  int depth,
80  Uint32 rmask,
81  Uint32 gmask,
82  Uint32 bmask,
83  Uint32 amask)
84  : surface_{SDL_CreateRGBSurface(flags, w, h, depth, rmask, gmask, bmask, amask)}
85  {
86  if (!surface_) throw Exception{"SDL_CreateRGBSurface"};
87  }
88 
91  void* pixels,
92  int w,
93  int h,
94  int depth,
95  int pitch,
96  Uint32 rmask,
97  Uint32 gmask,
98  Uint32 bmask,
99  Uint32 amask)
100  : surface_{SDL_CreateRGBSurfaceFrom(pixels, w, h, depth, pitch, rmask, gmask, bmask, amask)}
101  {
102  if (!surface_) throw Exception{"SDL_CreateRGBSurfaceFrom"};
103  }
104 
106  Surface(Uint32 flags, int w, int h, int depth, Uint32 format)
107  : surface_{SDL_CreateRGBSurfaceWithFormat(flags, w, h, depth, format)}
108  {
109  if (!surface_) throw Exception{"SDL_CreateRGBSurfaceWithFormat"};
110  }
111 
113  Surface(void* pixels, int w, int h, int depth, int pitch, int format)
114  : surface_{SDL_CreateRGBSurfaceWithFormatFrom(pixels, w, h, depth, pitch, format)}
115  {
116  if (!surface_) throw Exception{"SDL_CreateRGBSurfaceWithFormatFrom"};
117  }
118 
119 #ifdef CPP_SDL2_ENABLE_SDL_IMAGE
120  Surface(std::string const& filename) : surface_{IMG_Load(filename.c_str())}
122  {
123  if (!surface_) throw Exception{"IMG_Load"};
124  }
125 
126 #else
127  Surface(std::string const& filename) : surface_{nullptr}
129  {
130  SDL_SetError(
131  "Tried to call sdl::Surface(std::string const& filename) ctor. "
132  "This function should call IMG_Load() from SDL_Image.\n"
133  "This program was built without SDL_Image.\n"
134  "Please Install SDL_Image and #define CPP_SDL2_USE_SDL_IMAGE "
135  "before including sdl.hpp to use this functionality");
136  throw Exception("IMG_Load");
137  }
138 #endif
139 
141  ~Surface() { SDL_FreeSurface(surface_); }
142 
144  SDL_Surface* ptr() const { return surface_; }
145 
148  Surface with_format(SDL_PixelFormat const& format) const
149  {
150  auto s = SDL_ConvertSurface(surface_, &format, 0);
151  if (!s) throw Exception{"SDL_ConvertSurface"};
152  return Surface{s};
153  }
154 
157  Surface with_format(Uint32 format) const
158  {
159  auto s = SDL_ConvertSurfaceFormat(surface_, format, 0);
160  if (!s) throw Exception{"SDL_ConvertSurfaceFormat"};
161  return Surface{s};
162  }
163 
165  Surface& convert_to(SDL_PixelFormat const& format) { return *this = with_format(format); }
167  Surface& convert_to(Uint32 format) { return *this = with_format(format); }
168 
169 #if SDL_VERSION_ATLEAST(2, 0, 9)
170  bool has_colorkey() const { return SDL_HasColorKey(surface_) == SDL_TRUE; }
171 #endif
172 
174  void blit_on(Rect const& src, Surface& surf, Rect const& dst) const
175  {
176  // dst rectangle will *not* be modified by a blit
177  auto dstmut = const_cast<Rect&>(dst);
178  if (SDL_BlitSurface(surface_, &src, surf.surface_, &dstmut) != 0)
179  {
180  throw Exception{"SDL_BlitSurface"};
181  }
182  }
183 
185  void blit_on(Surface& surf, Rect const& dst) const
186  { // dst rectangle will *not* be modified by a blit
187  auto dstmut = const_cast<Rect&>(dst);
188  if (SDL_BlitSurface(surface_, nullptr, surf.surface_, &dstmut) != 0)
189  {
190  throw Exception{"SDL_BlitSurface"};
191  }
192  }
193 
195  int width() const { return surface_->w; }
197  int height() const { return surface_->h; }
199  Vec2i size() const { return Vec2i{width(), height()}; }
200 
202  SDL_PixelFormat const& pixelformat() const { return *surface_->format; }
203 
205  Uint32 format() const { return surface_->format->format; }
206 
208  Uint32 flags() const { return surface_->flags; }
209 
211  Rect cliprect() const
212  {
213  Rect r;
214  SDL_GetClipRect(surface_, &r);
215  return r;
216  }
217 
219  void disable_colorkey() const
220  {
221  if (SDL_SetColorKey(surface_, SDL_FALSE, 0) != 0) throw Exception{"SDL_SetColorKey"};
222  }
223 
225  void set_colorkey(Uint32 key) const
226  {
227  if (SDL_SetColorKey(surface_, SDL_TRUE, key) != 0) throw Exception{"SDL_SetColorKey"};
228  }
230  void set_colorkey(Color const& color) const
231  {
232  if (SDL_SetColorKey(surface_, SDL_TRUE, color.as_uint(pixelformat())) != 0)
233  {
234  throw Exception{"SDL_SetColorKey"};
235  }
236  }
237 
239  Color colorkey() const
240  {
241  Uint32 k;
242  if (SDL_GetColorKey(surface_, &k) != 0) throw Exception{"SDL_GetColorKey"};
243  return Color{k, pixelformat()};
244  }
245 
247  void set_blendmode(SDL_BlendMode const& bm) const
248  {
249  if (SDL_SetSurfaceBlendMode(surface_, bm) != 0) throw Exception{"SDL_SetSurfaceBlendMode"};
250  }
251  SDL_BlendMode blendmode() const
252  {
253  SDL_BlendMode bm;
254  if (SDL_GetSurfaceBlendMode(surface_, &bm) != 0) throw Exception{"SDL_GetSurfaceBlendMode"};
255  return bm;
256  }
257 
259  void set_colormod(Color const& color) const { set_colormod(color.r, color.g, color.b); }
261  void set_colormod(Uint8 r, Uint8 g, Uint8 b) const
262  {
263  if (SDL_SetSurfaceColorMod(surface_, r, g, b)) throw Exception{"SDL_SetSurfaceColorMod"};
264  }
265 
267  Color colormod() const
268  {
269  Color c;
270  if (SDL_GetSurfaceColorMod(surface_, &c.r, &c.g, &c.b) != 0)
271  throw Exception{"SDL_SetSurfaceColorMod"};
272  return c;
273  }
274 
276  void set_alphamod(Uint8 alpha) const
277  {
278  if (SDL_SetSurfaceAlphaMod(surface_, alpha) != 0) throw Exception{"SDL_SetSurfaceAlphaMod"};
279  }
281  Uint8 alphamod() const
282  {
283  Uint8 alpha;
284  if (SDL_GetSurfaceAlphaMod(surface_, &alpha) != 0)
285  throw Exception{"SDL_GetSurfaceAlphaMod"};
286  return alpha;
287  }
288 
290  void set_coloralphamod(Uint8 r, Uint8 g, Uint8 b, Uint8 a) const
291  {
292  set_colormod(r, g, b);
293  set_alphamod(a);
294  }
296  void set_coloralphamod(Color const& c) const
297  {
298  set_colormod(c.r, c.g, c.b);
299  set_alphamod(c.a);
300  }
303  {
304  auto c = colormod();
305  c.a = alphamod();
306  return c;
307  }
308 
312  [[nodiscard]] Lock lock()
313  {
314  if (SDL_LockSurface(surface_) != 0) throw Exception{"SDL_LockSurface"};
315  return Lock{*surface_};
316  }
317 
318 private:
320  SDL_Surface* surface_ = nullptr;
321 };
322 
323 } // namespace sdl
void set_alphamod(Uint8 alpha) const
Set alphamod.
Definition: surface.hpp:276
Surface with_format(SDL_PixelFormat const &format) const
Convert surface to given format.
Definition: surface.hpp:148
Surface with_format(Uint32 format) const
convert surface from given format
Definition: surface.hpp:157
void set_colormod(Color const &color) const
Set colormod.
Definition: surface.hpp:259
Vec2i size() const
Get size of surface.
Definition: surface.hpp:199
void disable_colorkey() const
disable colorkey
Definition: surface.hpp:219
void set_colorkey(Uint32 key) const
Set colorkey.
Definition: surface.hpp:225
Surface(Surface &&other) noexcept
Definition: surface.hpp:61
sdl::Rect, C++ wrapping of SDL_Rect
Definition: rect.hpp:11
Color colormod() const
Get colormod.
Definition: surface.hpp:267
bool has_colorkey() const
Definition: surface.hpp:170
Uint8 alphamod() const
Get alphamod.
Definition: surface.hpp:281
Surface & operator=(Surface &&other) noexcept
Definition: surface.hpp:63
Surface(SDL_Surface *surface)
Explicit converting ctor from C SDL_Surface to sdl::Surface.
Definition: surface.hpp:59
Generic templated 2D vector class.
Definition: vec2.hpp:24
void set_colorkey(Color const &color) const
Set colorkey.
Definition: surface.hpp:230
friend class Surface
Definition: surface.hpp:27
void blit_on(Surface &surf, Rect const &dst) const
Blit surface on another.
Definition: surface.hpp:185
Pixel at(size_t x, size_t y) const
Get pixel at specified location inside surface.
Definition: surface.hpp:33
SDL_PixelFormat const & pixelformat() const
Get surface&#39;s pixel format.
Definition: surface.hpp:202
Surface(void *pixels, int w, int h, int depth, int pitch, int format)
Create surface from array of pixels.
Definition: surface.hpp:113
SDL_Surface * surface_
Set surface pointer.
Definition: surface.hpp:320
~Lock()
Free the lock.
Definition: surface.hpp:48
void set_coloralphamod(Color const &c) const
Set color and alpha mod.
Definition: surface.hpp:296
Represent a lock to safely access surface content.
Definition: surface.hpp:25
Pixel at(Vec2i const &pos) const
Get pixel at given coordinates inside surface.
Definition: surface.hpp:31
C++ wrapping around the SDL_Color structure.
Definition: color.hpp:10
Define to deactivate exception support.
Definition: color.hpp:7
int height() const
Get height of surface.
Definition: surface.hpp:197
Uint32 flags() const
Get surface flags.
Definition: surface.hpp:208
void * raw_array() const
Get access to the raw array of pixels.
Definition: surface.hpp:45
Represent a 4 channel pixel.
Definition: pixel.hpp:10
SDL_BlendMode blendmode() const
Definition: surface.hpp:251
SDL_Surface * surface_
Raw pointer to the surface.
Definition: surface.hpp:55
Surface(Uint32 flags, int w, int h, int depth, Uint32 rmask, Uint32 gmask, Uint32 bmask, Uint32 amask)
Create surface for given parameters.
Definition: surface.hpp:75
allocator< U > a
Definition: simd.hpp:144
SDL_Surface * ptr() const
Get C SDL_Surface object.
Definition: surface.hpp:144
~Surface()
RAII dtor to automatically free the surface.
Definition: surface.hpp:141
void set_colormod(Uint8 r, Uint8 g, Uint8 b) const
Set colormod.
Definition: surface.hpp:261
Surface & convert_to(Uint32 format)
Convert this surface to specified format.
Definition: surface.hpp:167
Represent an SDL_Surface.
Definition: surface.hpp:21
constexpr Lock(SDL_Surface &surface_)
Private constructor for lock object.
Definition: surface.hpp:52
void set_coloralphamod(Uint8 r, Uint8 g, Uint8 b, Uint8 a) const
Set color and alpha mod.
Definition: surface.hpp:290
Lock lock()
Lock surface for raw access to pixel.
Definition: surface.hpp:312
Color coloralphamod() const
Get color and alpha mod.
Definition: surface.hpp:302
void blit_on(Rect const &src, Surface &surf, Rect const &dst) const
Blit surface on another.
Definition: surface.hpp:174
Pixel operator[](Vec2i const &pos) const
Get pixel at specified location via operator[].
Definition: surface.hpp:42
void set_blendmode(SDL_BlendMode const &bm) const
Set surface blend mode.
Definition: surface.hpp:247
Surface & convert_to(SDL_PixelFormat const &format)
Convert this surface to specified format.
Definition: surface.hpp:165
Uint32 format() const
Get surface format.
Definition: surface.hpp:205
Rect cliprect() const
Get surface clip rectangle.
Definition: surface.hpp:211
Color colorkey() const
Get color key.
Definition: surface.hpp:239
Define to deactivate exception support.
Definition: exception.hpp:21
Surface(void *pixels, int w, int h, int depth, int pitch, Uint32 rmask, Uint32 gmask, Uint32 bmask, Uint32 amask)
Create surface from array of pixels.
Definition: surface.hpp:90
Surface(Uint32 flags, int w, int h, int depth, Uint32 format)
Create surface with specified format.
Definition: surface.hpp:106
int width() const
Get width of surface.
Definition: surface.hpp:195
Uint32 as_uint(SDL_PixelFormat const &format) const
Return the color of the current object as a 32bit number (4 bytes)
Definition: color.hpp:55