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