The Battle for Wesnoth  1.19.0-dev
surface.cpp
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 #include "sdl/surface.hpp"
16 
17 #include "color.hpp"
18 #include "sdl/rect.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 
84 bool operator<(const surface& a, const surface& b)
85 {
86  return a.get() < b.get();
87 }
88 
89 std::ostream& operator<<(std::ostream& stream, const surface& surf)
90 {
91  if(!surf.get()) {
92  stream << "<null surface>";
93  } else if(!surf->format) {
94  stream << "<invalid surface>";
95  } else {
96  stream << "{ " << surf->w << 'x' << surf->h << '@'
97  << unsigned(surf->format->BitsPerPixel) << "bpp"
98  << (surf->format->palette ? " indexed" : "")
99  << " clip_rect=[" << surf->clip_rect
100  << "] refcount=" << surf->refcount
101  << " }";
102  }
103 
104  return stream;
105 }
void free_surface()
Definition: surface.cpp:77
void assign_surface_internal(SDL_Surface *surf)
Definition: surface.cpp:69
bool is_neutral() const
Check that the surface is neutral bpp 32.
Definition: surface.cpp:40
static const SDL_PixelFormat neutral_pixel_format
Definition: surface.hpp:109
surface clone() const
Makes a copy of this surface.
Definition: surface.cpp:63
SDL_Surface * surface_
Definition: surface.hpp:107
SDL_Surface * get() const
Definition: surface.hpp:91
surface()
Definition: surface.hpp:27
static void add_surface_ref(SDL_Surface *surf)
Definition: surface.hpp:96
surface & make_neutral()
Converts this surface to a neutral format if it is not already.
Definition: surface.cpp:49
constexpr uint32_t SDL_ALPHA_MASK
Definition: color.hpp:25
constexpr uint32_t SDL_RED_MASK
Definition: color.hpp:26
int w
Contains the SDL_Rect helper code.
bool operator<(const surface &a, const surface &b)
Definition: surface.cpp:84
std::ostream & operator<<(std::ostream &stream, const surface &surf)
Definition: surface.cpp:89
#define h
#define a
#define b