The Battle for Wesnoth  1.15.2+dev
surface.hpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2003 - 2018 the Battle for Wesnoth Project https://www.wesnoth.org/
3 
4  This program is free software; you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation; either version 2 of the License, or
7  (at your option) any later version.
8  This program is distributed in the hope that it will be useful,
9  but WITHOUT ANY WARRANTY.
10 
11  See the COPYING file for more details.
12 */
13 
14 #pragma once
15 
16 #include "global.hpp"
17 #include "utils/const_clone.hpp"
18 
19 #include <SDL2/SDL.h>
20 
21 #include <ostream>
22 
23 class CVideo;
24 
25 class surface
26 {
27 public:
28  surface() : surface_(nullptr)
29  {}
30 
31  surface(SDL_Surface* surf);
32 
33  /** Allocates a new surface with the given dimensions. */
34  surface(int w, int h);
35 
36  surface(const surface& s) : surface_(s.get())
37  {
39  }
40 
41  surface(surface&& s) noexcept : surface_(s.get())
42  {
43  s.surface_ = nullptr;
44  }
45 
47  {
48  free_surface();
49  }
50 
52  {
54  return *this;
55  }
56 
57  surface& operator=(SDL_Surface* surf)
58  {
60  return *this;
61  }
62 
63  surface& operator=(surface&& s) noexcept
64  {
65  free_surface();
66  surface_ = s.surface_;
67  s.surface_ = nullptr;
68  return *this;
69  }
70 
71  // Intended to be used when SDL has already freed the surface
72  void clear_without_free() { surface_ = nullptr; }
73 
74  /**
75  * Check that the surface is neutral bpp 32.
76  *
77  * The surface may have an empty alpha channel.
78  *
79  * @returns The status @c true if neutral, @c false if not.
80  */
81  bool is_neutral() const;
82 
83  /**
84  * Converts this surface to a neutral format if it is not already.
85  *
86  * @returns A reference to this object for chaining convenience.
87  */
89 
90  /**
91  * Makes a copy of this surface. The copy will be in the 'neutral' pixel format.
92  *
93  * Note this is creates a new, duplicate surface in memory. Making a copy of this
94  * 'surface' object will *not* duplicate the surface itself since we only hold a
95  * pointer to the actual surface.
96  */
97  surface clone() const;
98 
99  operator SDL_Surface*() const { return surface_; }
100 
101  SDL_Surface* get() const { return surface_; }
102 
103  SDL_Surface* operator->() const { return surface_; }
104 
105 private:
106  static void add_surface_ref(SDL_Surface* surf)
107  {
108  if(surf) {
109  ++surf->refcount;
110  }
111  }
112 
113  void assign_surface_internal(SDL_Surface* surf);
114 
115  void free_surface();
116 
117  SDL_Surface* surface_;
118 
119  static const SDL_PixelFormat neutral_pixel_format;
120 };
121 
122 bool operator<(const surface& a, const surface& b);
123 
124 std::ostream& operator<<(std::ostream& stream, const surface& surf);
125 
127 {
129  surface_restorer(class CVideo* target, const SDL_Rect& rect);
130  ~surface_restorer();
131 
132  void restore() const;
133  void restore(const SDL_Rect& dst) const;
134  void update();
135  void cancel();
136 
137  const SDL_Rect& area() const { return rect_; }
138 
139 private:
140  class CVideo* target_;
141  SDL_Rect rect_;
143 };
144 
145 /**
146  * Helper class for pinning SDL surfaces into memory.
147  * @note This class should be used only with neutral surfaces, so that
148  * the pointer returned by #pixels is meaningful.
149  */
150 template<typename T>
152 {
153 private:
155 
156 public:
157  surface_locker(T& surf) : surface_(surf), locked_(false)
158  {
159  if(SDL_MUSTLOCK(surface_)) {
160  locked_ = SDL_LockSurface(surface_) == 0;
161  }
162  }
163 
165  {
166  if(locked_) {
167  SDL_UnlockSurface(surface_);
168  }
169  }
170 
171  pixel_t* pixels() const { return reinterpret_cast<pixel_t*>(surface_->pixels); }
172 
173 private:
175  bool locked_;
176 };
177 
180 
182 {
183  // if r is nullptr, clip to the full size of the surface.
184  clip_rect_setter(const surface &surf, const SDL_Rect* r, bool operate = true) : surface_(surf), rect_(), operate_(operate)
185  {
186  if(operate_ && surface_.get()){
187  SDL_GetClipRect(surface_, &rect_);
188  SDL_Rect final_rect = { 0, 0, 0, 0 };
189 
190  if(r) {
191  SDL_IntersectRect(&rect_, r, &final_rect);
192  } else {
193  final_rect.w = surface_->w;
194  final_rect.h = surface_->h;
195  }
196 
197  SDL_SetClipRect(surface_, &final_rect);
198  }
199  }
200 
202  {
203  if(operate_ && surface_.get()) {
204  SDL_SetClipRect(surface_, &rect_);
205  }
206  }
207 
208 private:
210  SDL_Rect rect_;
211  const bool operate_;
212 };
pixel_t * pixels() const
Definition: surface.hpp:171
SDL_Surface * get() const
Definition: surface.hpp:101
void free_surface()
Definition: surface.cpp:89
#define a
Definition: video.hpp:31
surface_locker(T &surf)
Definition: surface.hpp:157
const SDL_Rect & area() const
Definition: surface.hpp:137
static void add_surface_ref(SDL_Surface *surf)
Definition: surface.hpp:106
#define h
surface(const surface &s)
Definition: surface.hpp:36
void assign_surface_internal(SDL_Surface *surf)
Definition: surface.cpp:81
surface & operator=(surface &&s) noexcept
Definition: surface.hpp:63
surface clone() const
Makes a copy of this surface.
Definition: surface.cpp:75
surface & operator=(SDL_Surface *surf)
Definition: surface.hpp:57
surface surface_
Definition: surface.hpp:142
#define b
surface()
Definition: surface.hpp:28
surface(surface &&s) noexcept
Definition: surface.hpp:41
surface & operator=(const surface &s)
Definition: surface.hpp:51
surface & make_neutral()
Converts this surface to a neutral format if it is not already.
Definition: surface.cpp:61
SDL_Rect rect_
Definition: surface.hpp:141
utils::const_clone_t< uint32_t, T > pixel_t
Definition: surface.hpp:154
SDL_Rect rect_
Definition: surface.hpp:210
const bool operate_
Definition: surface.hpp:211
bool operator<(const surface &a, const surface &b)
Definition: surface.cpp:170
std::ostream & operator<<(std::ostream &stream, const surface &surf)
Definition: surface.cpp:175
class CVideo * target_
Definition: surface.hpp:140
static map_location::DIRECTION s
SDL_Surface * surface_
Definition: surface.hpp:117
Helper class for pinning SDL surfaces into memory.
Definition: surface.hpp:151
SDL_Surface * operator->() const
Definition: surface.hpp:103
int w
surface surface_
Definition: surface.hpp:209
bool is_neutral() const
Check that the surface is neutral bpp 32.
Definition: surface.cpp:52
void clear_without_free()
Definition: surface.hpp:72
clip_rect_setter(const surface &surf, const SDL_Rect *r, bool operate=true)
Definition: surface.hpp:184
typename const_clone< D, S >::type const_clone_t
Definition: const_clone.hpp:59
static const SDL_PixelFormat neutral_pixel_format
Definition: surface.hpp:119
~surface()
Definition: surface.hpp:46