1 /*
2 libSDL2pp - C++11 bindings/wrapper for SDL2
3 Copyright (C) 2014-2015 Dmitry Marakasov <amdmi3@amdmi3.ru>
4
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
8
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
12
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software
15 in a product, an acknowledgment in the product documentation would be
16 appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and must not be
18 misrepresented as being the original software.
19 3. This notice may not be removed or altered from any source distribution.
20 */
21
22 #include <vector>
23 #include <cassert>
24
25 #include <SDL2pp/Config.hh>
26
27 #include <SDL_surface.h>
28 #ifdef SDL2PP_WITH_IMAGE
29 # include <SDL_image.h>
30 #endif
31
32 #include <SDL2pp/Surface.hh>
33 #include <SDL2pp/Exception.hh>
34 #ifdef SDL2PP_WITH_IMAGE
35 # include <SDL2pp/RWops.hh>
36 #endif
37
38 namespace SDL2pp {
39
Surface(SDL_Surface * surface)40 Surface::Surface(SDL_Surface* surface) : surface_(surface) {
41 assert(surface);
42 }
43
Surface(Uint32 flags,int width,int height,int depth,Uint32 Rmask,Uint32 Gmask,Uint32 Bmask,Uint32 Amask)44 Surface::Surface(Uint32 flags, int width, int height, int depth, Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask) {
45 if ((surface_ = SDL_CreateRGBSurface(flags, width, height, depth, Rmask, Gmask, Bmask, Amask)) == nullptr)
46 throw Exception("SDL_CreateRGBSurface");
47 }
48
Surface(void * pixels,int width,int height,int depth,int pitch,Uint32 Rmask,Uint32 Gmask,Uint32 Bmask,Uint32 Amask)49 Surface::Surface(void* pixels, int width, int height, int depth, int pitch, Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask) {
50 if ((surface_ = SDL_CreateRGBSurfaceFrom(pixels, width, height, depth, pitch, Rmask, Gmask, Bmask, Amask)) == nullptr)
51 throw Exception("SDL_CreateRGBSurfaceFrom");
52 }
53
54 #ifdef SDL2PP_WITH_IMAGE
Surface(RWops & rwops)55 Surface::Surface(RWops& rwops) {
56 if ((surface_ = IMG_Load_RW(rwops.Get(), 0)) == nullptr)
57 throw Exception("IMG_Load_RW");
58 }
59
Surface(const std::string & path)60 Surface::Surface(const std::string& path) {
61 if ((surface_ = IMG_Load(path.c_str())) == nullptr)
62 throw Exception("IMG_Load");
63 }
64 #endif
65
~Surface()66 Surface::~Surface() {
67 if (surface_ != nullptr)
68 SDL_FreeSurface(surface_);
69 }
70
Surface(Surface && other)71 Surface::Surface(Surface&& other) noexcept : surface_(other.surface_) {
72 other.surface_ = nullptr;
73 }
74
operator =(Surface && other)75 Surface& Surface::operator=(Surface&& other) noexcept {
76 if (&other == this)
77 return *this;
78 if (surface_ != nullptr)
79 SDL_FreeSurface(surface_);
80 surface_ = other.surface_;
81 other.surface_ = nullptr;
82 return *this;
83 }
84
Get() const85 SDL_Surface* Surface::Get() const {
86 return surface_;
87 }
88
Convert(const SDL_PixelFormat & format)89 Surface Surface::Convert(const SDL_PixelFormat& format) {
90 SDL_Surface* surface = SDL_ConvertSurface(surface_, &format, 0);
91 if (surface == nullptr)
92 throw Exception("SDL_ConvertSurface");
93 return SDL2pp::Surface(surface);
94 }
95
Convert(Uint32 pixel_format)96 Surface Surface::Convert(Uint32 pixel_format) {
97 SDL_Surface* surface = SDL_ConvertSurfaceFormat(surface_, pixel_format, 0);
98 if (surface == nullptr)
99 throw Exception("SDL_ConvertSurfaceFormat");
100 return SDL2pp::Surface(surface);
101 }
102
Blit(const Optional<Rect> & srcrect,Surface & dst,const Rect & dstrect)103 void Surface::Blit(const Optional<Rect>& srcrect, Surface& dst, const Rect& dstrect) {
104 SDL_Rect tmpdstrect = dstrect; // 4th argument is non-const; does it modify rect?
105 if (SDL_BlitSurface(surface_, srcrect ? &*srcrect : nullptr, dst.Get(), &tmpdstrect) != 0)
106 throw Exception("SDL_BlitSurface");
107 }
108
BlitScaled(const Optional<Rect> & srcrect,Surface & dst,const Optional<Rect> & dstrect)109 void Surface::BlitScaled(const Optional<Rect>& srcrect, Surface& dst, const Optional<Rect>& dstrect) {
110 SDL_Rect tmpdstrect; // 4th argument is non-const; does it modify rect?
111 if (dstrect)
112 tmpdstrect = *dstrect;
113 if (SDL_BlitScaled(surface_, srcrect ? &*srcrect : nullptr, dst.Get(), dstrect ? &tmpdstrect : nullptr) != 0)
114 throw Exception("SDL_BlitScaled");
115 }
116
Lock()117 Surface::LockHandle Surface::Lock() {
118 return LockHandle(this);
119 }
120
GetClipRect() const121 Rect Surface::GetClipRect() const {
122 SDL_Rect rect;
123 SDL_GetClipRect(surface_, &rect);
124 return Rect(rect);
125 }
126
GetColorKey() const127 Uint32 Surface::GetColorKey() const {
128 Uint32 key;
129 if (SDL_GetColorKey(surface_, &key) != 0)
130 throw Exception("SDL_GetColorKey");
131 return key;
132 }
133
GetAlphaMod() const134 Uint8 Surface::GetAlphaMod() const {
135 Uint8 alpha;
136 if (SDL_GetSurfaceAlphaMod(surface_, &alpha) != 0)
137 throw Exception("SDL_GetSurfaceAlphaMod");
138 return alpha;
139 }
140
GetBlendMode() const141 SDL_BlendMode Surface::GetBlendMode() const {
142 SDL_BlendMode blendMode;
143 if (SDL_GetSurfaceBlendMode(surface_, &blendMode) != 0)
144 throw Exception("SDL_GetSurfaceBlendMode");
145 return blendMode;
146 }
147
GetColorAndAlphaMod() const148 Color Surface::GetColorAndAlphaMod() const {
149 Color color;
150 GetColorMod(color.r, color.g, color.b);
151 color.a = GetAlphaMod();
152 return color;
153 }
154
GetColorMod(Uint8 & r,Uint8 & g,Uint8 & b) const155 void Surface::GetColorMod(Uint8& r, Uint8& g, Uint8& b) const {
156 if (SDL_GetSurfaceColorMod(surface_, &r, &g, &b) != 0)
157 throw Exception("SDL_GetSurfaceColorMod");
158 }
159
SetClipRect(const Optional<Rect> & rect)160 Surface& Surface::SetClipRect(const Optional<Rect>& rect) {
161 if (SDL_SetClipRect(surface_, rect ? &*rect : nullptr) != SDL_TRUE)
162 throw Exception("SDL_SetClipRect");
163 return *this;
164 }
165
SetColorKey(bool flag,Uint32 key)166 Surface& Surface::SetColorKey(bool flag, Uint32 key) {
167 if (SDL_SetColorKey(surface_, flag, key) != 0)
168 throw Exception("SDL_SetColorKey");
169 return *this;
170 }
171
SetAlphaMod(Uint8 alpha)172 Surface& Surface::SetAlphaMod(Uint8 alpha) {
173 if (SDL_SetSurfaceAlphaMod(surface_, alpha) != 0)
174 throw Exception("SDL_SetSurfaceAlphaMod");
175 return *this;
176 }
177
SetBlendMode(SDL_BlendMode blendMode)178 Surface& Surface::SetBlendMode(SDL_BlendMode blendMode) {
179 if (SDL_SetSurfaceBlendMode(surface_, blendMode) != 0)
180 throw Exception("SDL_SetSurfaceBlendMode");
181 return *this;
182 }
183
SetColorMod(Uint8 r,Uint8 g,Uint8 b)184 Surface& Surface::SetColorMod(Uint8 r, Uint8 g, Uint8 b) {
185 if (SDL_SetSurfaceColorMod(surface_, r, g, b) != 0)
186 throw Exception("SDL_SetSurfaceColorMod");
187 return *this;
188 }
189
SetColorAndAlphaMod(const Color & color)190 Surface& Surface::SetColorAndAlphaMod(const Color& color) {
191 return SetColorMod(color.r, color.g, color.b).SetAlphaMod(color.a);
192 }
193
SetRLE(bool flag)194 Surface& Surface::SetRLE(bool flag) {
195 if (SDL_SetSurfaceRLE(surface_, flag ? 1 : 0) != 0)
196 throw Exception("SDL_SetSurfaceRLE");
197 return *this;
198 }
199
FillRect(const Optional<Rect> & rect,Uint32 color)200 Surface& Surface::FillRect(const Optional<Rect>& rect, Uint32 color) {
201 if (SDL_FillRect(surface_, rect ? &*rect : nullptr, color) != 0)
202 throw Exception("SDL_FillRect");
203 return *this;
204 }
205
FillRects(const Rect * rects,int count,Uint32 color)206 Surface& Surface::FillRects(const Rect* rects, int count, Uint32 color) {
207 std::vector<SDL_Rect> sdl_rects;
208 sdl_rects.reserve(static_cast<size_t>(count));
209 for (const Rect* r = rects; r != rects + count; ++r)
210 sdl_rects.emplace_back(*r);
211
212 if (SDL_FillRects(surface_, sdl_rects.data(), count, color) != 0)
213 throw Exception("SDL_FillRects");
214 return *this;
215 }
216
GetWidth() const217 int Surface::GetWidth() const {
218 return surface_->w;
219 }
220
GetHeight() const221 int Surface::GetHeight() const {
222 return surface_->h;
223 }
224
GetSize() const225 Point Surface::GetSize() const {
226 return Point(surface_->w, surface_->h);
227 }
228
GetFormat() const229 Uint32 Surface::GetFormat() const {
230 return surface_->format->format;
231 }
232
233 }
234