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