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