surface.cpp 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  1. #include "simple/support/function_utils.hpp"
  2. #include "simple/support/enum.hpp"
  3. #include "simple/sdlcore/utils.hpp"
  4. #include "surface.h"
  5. using simple::support::to_integer;
  6. namespace simple::graphical
  7. {
  8. surface::surface(const char* filename)
  9. : sdl_surface_wrapper(SDL_LoadBMP(filename), SDL_FreeSurface),
  10. _format(this->guts()->format)
  11. {}
  12. surface::surface(const surface& other)
  13. : sdl_surface_wrapper
  14. (
  15. #if SDL_VERSION_ATLEAST(2,0,6)
  16. SDL_DuplicateSurface(other.guts().get()),
  17. #else
  18. SDL_ConvertSurface(other.guts().get(), other.guts()->format, other.guts()->flags),
  19. #endif
  20. SDL_FreeSurface
  21. ),
  22. _format(this->guts()->format)
  23. {}
  24. surface::surface(int2 size, const pixel_format& format)
  25. : sdl_surface_wrapper
  26. (
  27. SDL_CreateRGBSurface
  28. (
  29. 0,
  30. size.x(), size.y(),
  31. format.bits(),
  32. format.red_mask(), format.green_mask(), format.blue_mask(), format.alpha_mask()
  33. ),
  34. SDL_FreeSurface
  35. ),
  36. _format(this->guts()->format)
  37. {
  38. if(format.palette())
  39. SDL_SetSurfacePalette(guts().get(), format.guts().get()->palette);
  40. }
  41. surface::surface(byte* pixels, int2 size, const pixel_format& format, int pitch)
  42. : sdl_surface_wrapper
  43. (
  44. SDL_CreateRGBSurfaceFrom
  45. (
  46. pixels,
  47. size.x(), size.y(),
  48. format.bits(),
  49. pitch ? pitch : format.bytes() * size.x(),
  50. format.red_mask(), format.green_mask(), format.blue_mask(), format.alpha_mask()
  51. ),
  52. SDL_FreeSurface
  53. ),
  54. _format(this->guts()->format)
  55. {
  56. if(format.palette())
  57. SDL_SetSurfacePalette(guts().get(), format.guts().get()->palette);
  58. }
  59. surface::surface(std::unique_ptr<byte[]> pixels, int2 size, const pixel_format& format, int pitch)
  60. : sdl_surface_wrapper
  61. (
  62. SDL_CreateRGBSurfaceFrom
  63. (
  64. pixels.get(),
  65. size.x(), size.y(),
  66. format.bits(),
  67. pitch ? pitch : format.bytes() * size.x(),
  68. format.red_mask(), format.green_mask(), format.blue_mask(), format.alpha_mask()
  69. ),
  70. SDL_FreeSurface
  71. ),
  72. _format(this->guts()->format),
  73. pixels_owner(pixels.release(), [](byte* x){ delete [] x; }) // hmmm... weird... but true
  74. {
  75. if(format.palette())
  76. SDL_SetSurfacePalette(guts().get(), format.guts().get()->palette);
  77. }
  78. surface::surface(std::unique_ptr<byte[], void(*)(byte*)> pixels, int2 size, const pixel_format& format, int pitch)
  79. : sdl_surface_wrapper
  80. (
  81. SDL_CreateRGBSurfaceFrom
  82. (
  83. pixels.get(),
  84. size.x(), size.y(),
  85. format.bits(),
  86. pitch ? pitch : format.bytes() * size.x(),
  87. format.red_mask(), format.green_mask(), format.blue_mask(), format.alpha_mask()
  88. ),
  89. SDL_FreeSurface
  90. ),
  91. _format(this->guts()->format),
  92. pixels_owner(std::move(pixels))
  93. {
  94. if(format.palette())
  95. SDL_SetSurfacePalette(guts().get(), format.guts().get()->palette);
  96. }
  97. #if SDL_VERSION_ATLEAST(2,0,5)
  98. surface::surface(int2 size, pixel_format::type format)
  99. : sdl_surface_wrapper
  100. (
  101. SDL_CreateRGBSurfaceWithFormat
  102. (
  103. 0,
  104. size.x(), size.y(),
  105. 0,
  106. to_integer(format)
  107. ),
  108. SDL_FreeSurface
  109. ),
  110. _format(this->guts()->format)
  111. {}
  112. surface::surface(byte* pixels, int2 size, pixel_format::type format, int pitch)
  113. : sdl_surface_wrapper
  114. (
  115. SDL_CreateRGBSurfaceWithFormatFrom
  116. (
  117. pixels,
  118. size.x(), size.y(),
  119. 0,
  120. pitch ? pitch : SDL_BYTESPERPIXEL(to_integer(format)) * size.x(),
  121. to_integer(format)
  122. ),
  123. SDL_FreeSurface
  124. ),
  125. _format(this->guts()->format)
  126. {}
  127. surface::surface(std::unique_ptr<byte[]> pixels, int2 size, pixel_format::type format, int pitch)
  128. : sdl_surface_wrapper
  129. (
  130. SDL_CreateRGBSurfaceWithFormatFrom
  131. (
  132. pixels.get(),
  133. size.x(), size.y(),
  134. 0,
  135. pitch ? pitch : SDL_BYTESPERPIXEL(to_integer(format)) * size.x(),
  136. to_integer(format)
  137. ),
  138. SDL_FreeSurface
  139. ),
  140. _format(this->guts()->format),
  141. pixels_owner(pixels.release(), [](byte* x){ delete [] x; })
  142. {}
  143. surface::surface(std::unique_ptr<byte[], void(*)(byte*)> pixels, int2 size, pixel_format::type format, int pitch)
  144. : sdl_surface_wrapper
  145. (
  146. SDL_CreateRGBSurfaceWithFormatFrom
  147. (
  148. pixels.get(),
  149. size.x(), size.y(),
  150. 0,
  151. pitch ? pitch : SDL_BYTESPERPIXEL(to_integer(format)) * size.x(),
  152. to_integer(format)
  153. ),
  154. SDL_FreeSurface
  155. ),
  156. _format(this->guts()->format),
  157. pixels_owner(std::move(pixels))
  158. {}
  159. #endif
  160. surface::surface(SDL_Surface* guts, Deleter deleter)
  161. : sdl_surface_wrapper(guts, deleter),
  162. _format(this->guts()->format)
  163. {}
  164. surface::free_pixel_format::free_pixel_format(SDL_PixelFormat* guts)
  165. : pixel_format(guts, support::nop)
  166. {}
  167. const pixel_format& surface::format() const
  168. {
  169. return _format;
  170. }
  171. int2 surface::size() const
  172. {
  173. return {guts()->w, guts()->h};
  174. }
  175. blend_mode surface::blend() const noexcept
  176. {
  177. SDL_BlendMode result;
  178. SDL_GetSurfaceBlendMode(guts().get(), &result);
  179. return static_cast<blend_mode>(result);
  180. }
  181. void surface::blend(blend_mode new_value) const noexcept
  182. {
  183. SDL_SetSurfaceBlendMode
  184. (
  185. guts().get(),
  186. static_cast<SDL_BlendMode>(support::to_integer(new_value))
  187. );
  188. }
  189. uint8_t surface::alpha() const noexcept
  190. {
  191. uint8_t result;
  192. SDL_GetSurfaceAlphaMod(guts().get(), &result);
  193. return result;
  194. }
  195. void surface::alpha(uint8_t new_value) const noexcept
  196. {
  197. SDL_SetSurfaceAlphaMod(guts().get(), new_value);
  198. }
  199. rgb_pixel surface::color() const noexcept
  200. {
  201. rgb_pixel result;
  202. SDL_GetSurfaceColorMod(guts().get(), &result.r(), &result.g(), &result.b());
  203. return result;
  204. }
  205. void surface::color(rgb_pixel new_value) const noexcept
  206. {
  207. SDL_SetSurfaceColorMod(guts().get(), new_value.r(), new_value.g(), new_value.b());
  208. }
  209. pixel_writer_variant pixel_writer_from_format(pixel_byte* data, int2 size, int pitch, int bpp)
  210. {
  211. int2 raw_size = size;
  212. raw_size.x() *= bpp;
  213. switch(bpp)
  214. {
  215. case 2:
  216. return pixel_writer<uint16_t, pixel_byte>(
  217. data, raw_size, pitch);
  218. case 3:
  219. return pixel_writer<rgb_pixel, pixel_byte>(
  220. data, raw_size, pitch);
  221. case 4:
  222. return pixel_writer<rgba_pixel, pixel_byte>(
  223. data, raw_size, pitch);
  224. default:
  225. return pixel_writer<pixel_byte>(
  226. data, raw_size, pitch);
  227. }
  228. }
  229. pixel_writer_variant surface::pixels() const noexcept
  230. {
  231. return pixel_writer_from_format(
  232. reinterpret_cast<byte*>(guts()->pixels),
  233. size(), guts()->pitch, format().bytes());
  234. }
  235. void surface::save(const char* filename) const
  236. {
  237. sdlcore::utils::throw_error(SDL_SaveBMP(guts().get(), filename));
  238. }
  239. } // namespace simple::graphical