The Battle for Wesnoth  1.17.0-dev
surface.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2003 - 2021
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 #include "sdl/surface.hpp"
16 
17 #include "sdl/rect.hpp"
18 #include "video.hpp"
19 
20 const SDL_PixelFormat surface::neutral_pixel_format = []() {
21  return *SDL_CreateRGBSurfaceWithFormat(0, 1, 1, 32, SDL_PIXELFORMAT_ARGB8888)->format;
22 }();
23 
24 surface::surface(SDL_Surface* surf)
25  : surface_(surf)
26 {
27  make_neutral(); // EXTREMELY IMPORTANT!
28 }
29 
30 surface::surface(int w, int h)
31  : surface_(nullptr)
32 {
33  if (w < 0 || h < 0) {
34  throw std::invalid_argument("Creating surface with negative dimensions");
35  }
36 
37  surface_ = SDL_CreateRGBSurfaceWithFormat(0, w, h, neutral_pixel_format.BitsPerPixel, neutral_pixel_format.format);
38 }
39 
40 bool surface::is_neutral() const
41 {
42  return surface_
43  && SDL_ISPIXELFORMAT_INDEXED(surface_->format->format) == SDL_FALSE
44  && surface_->format->BytesPerPixel == 4
45  && surface_->format->Rmask == SDL_RED_MASK
46  && (surface_->format->Amask | SDL_ALPHA_MASK) == SDL_ALPHA_MASK;
47 }
48 
50 {
51  if(surface_ && !is_neutral()) {
52  SDL_Surface* res = SDL_ConvertSurface(surface_, &neutral_pixel_format, 0);
53 
54  // Ensure we don't leak memory with the old surface.
55  free_surface();
56 
57  surface_ = res;
58  }
59 
60  return *this;
61 }
62 
64 {
65  // Use SDL_ConvertSurface to make a copy
66  return surface(SDL_ConvertSurface(surface_, &neutral_pixel_format, 0));
67 }
68 
69 void surface::assign_surface_internal(SDL_Surface* surf)
70 {
71  add_surface_ref(surf); // Needs to be done before assignment to avoid corruption on "a = a;"
72  free_surface();
73  surface_ = surf;
74  make_neutral(); // EXTREMELY IMPORTANT!
75 }
76 
78 {
79  if(surface_) {
80  SDL_FreeSurface(surface_);
81  }
82 }
83 
85  : target_(nullptr)
86  , rect_(sdl::empty_rect)
87  , surface_(nullptr)
88 {
89 }
90 
91 surface_restorer::surface_restorer(CVideo* target, const SDL_Rect& rect)
92  : target_(target)
93  , rect_(rect)
94  , surface_(nullptr)
95 {
96  update();
97 }
98 
100 {
101  restore();
102 }
103 
104 void surface_restorer::restore(const SDL_Rect& dst) const
105 {
106  if(!surface_) {
107  return;
108  }
109 
110  SDL_Rect dst2 = sdl::intersect_rects(dst, rect_);
111  if(dst2.w == 0 || dst2.h == 0) {
112  return;
113  }
114 
115  SDL_Rect src = dst2;
116  src.x -= rect_.x;
117  src.y -= rect_.y;
118  sdl_blit(surface_, &src, target_->getSurface(), &dst2);
119 }
120 
122 {
123  if(!surface_) {
124  return;
125  }
126 
127  SDL_Rect dst = rect_;
128  sdl_blit(surface_, nullptr, target_->getSurface(), &dst);
129 }
130 
132 {
133  if(rect_.w <= 0 || rect_.h <= 0) {
134  surface_ = nullptr;
135  } else {
137  }
138 }
139 
141 {
142  surface_ = nullptr;
143 }
144 
145 bool operator<(const surface& a, const surface& b)
146 {
147  return a.get() < b.get();
148 }
149 
150 std::ostream& operator<<(std::ostream& stream, const surface& surf)
151 {
152  if(!surf.get()) {
153  stream << "<null surface>";
154  } else if(!surf->format) {
155  stream << "<invalid surface>";
156  } else {
157  stream << "{ " << surf->w << 'x' << surf->h << '@'
158  << unsigned(surf->format->BitsPerPixel) << "bpp"
159  << (surf->format->palette ? " indexed" : "")
160  << " clip_rect=[" << surf->clip_rect
161  << "] refcount=" << surf->refcount
162  << " }";
163  }
164 
165  return stream;
166 }
SDL_Surface * get() const
Definition: surface.hpp:92
void free_surface()
Definition: surface.cpp:77
const uint32_t SDL_ALPHA_MASK
Definition: color.hpp:29
#define a
Definition: video.hpp:32
bool operator<(const surface &a, const surface &b)
Definition: surface.cpp:145
static void add_surface_ref(SDL_Surface *surf)
Definition: surface.hpp:97
SDL_Rect intersect_rects(const SDL_Rect &rect1, const SDL_Rect &rect2)
Calculates the intersection of two rectangles.
Definition: rect.cpp:40
#define h
surface get_surface_portion(const surface &src, SDL_Rect &area)
Get a portion of the screen.
Definition: utils.cpp:2158
void assign_surface_internal(SDL_Surface *surf)
Definition: surface.cpp:69
surface clone() const
Makes a copy of this surface.
Definition: surface.cpp:63
surface & getSurface()
Returns a reference to the framebuffer.
Definition: video.cpp:483
surface surface_
Definition: surface.hpp:133
#define b
surface()
Definition: surface.hpp:28
const uint32_t SDL_RED_MASK
Definition: color.hpp:30
surface & make_neutral()
Converts this surface to a neutral format if it is not already.
Definition: surface.cpp:49
SDL_Rect rect_
Definition: surface.hpp:132
class CVideo * target_
Definition: surface.hpp:131
SDL_Surface * surface_
Definition: surface.hpp:108
int w
void restore() const
Definition: surface.cpp:121
bool is_neutral() const
Check that the surface is neutral bpp 32.
Definition: surface.cpp:40
Contains the SDL_Rect helper code.
constexpr const SDL_Rect empty_rect
Definition: rect.hpp:32
static const SDL_PixelFormat neutral_pixel_format
Definition: surface.hpp:110
void sdl_blit(const surface &src, SDL_Rect *src_rect, surface &dst, SDL_Rect *dst_rect)
Definition: utils.hpp:32
std::ostream & operator<<(std::ostream &stream, const surface &surf)
Definition: surface.cpp:150