00001
00020 #include "config.h"
00021 #include "utils.hpp"
00022
00023 #include <iostream>
00024 #include <sstream>
00025 #include <algorithm>
00026
00027 #include <boost/shared_ptr.hpp>
00028
00029 #include <SDL/SDL.h>
00030
00031 #include <libnebular.hpp>
00032 #include <libnebular-plugin.hpp>
00033
00034 #ifndef SDL_UTILS_HPP_
00035 #define SDL_UTILS_HPP_
00036
00037 using boost::shared_ptr;
00038 using std::clog;
00039 using std::endl;
00040
00041 using libnebular::Picture;
00042 using libnebular::Integer;
00043 using libnebular::Blob;
00044
00045 #ifdef HAVE_SDL_SDL_H
00046
00048 #define CHECKZ_SDL( x ) do{ \
00049 if((x) != 0) { \
00050 std::ostringstream tmpOut; \
00051 tmpOut << "SDL: \"" << SDL_GetError() << "\" at line " << __LINE__ << " of file " << __FILE__ << ": \"" << #x << "\""; \
00052 throw std::runtime_error(tmpOut.str()); \
00053 } \
00054 }while(false)
00055
00057 #define CHECKNZ_SDL( x ) do{ \
00058 if((x) == 0) { \
00059 std::ostringstream tmpOut; \
00060 tmpOut << "SDL: \"" << SDL_GetError() << "\" at line " << __LINE__ << " of file " << __FILE__ << ": \"" << #x << "\" is 0"; \
00061 throw std::runtime_error(tmpOut.str()); \
00062 } \
00063 }while(false)
00064
00066 class SdlSurfaceHolder: public shared_ptr<SDL_Surface>{
00067 private:
00071 class Deleter{
00072 public:
00073 void operator()(element_type *p){
00074 SDL_FreeSurface( p );
00075 }
00076 };
00077 public:
00079 static SdlSurfaceHolder createWithNullDeleter(SDL_Surface *hangingSurf){
00080 return SdlSurfaceHolder(
00081 hangingSurf,
00082 null_deleter()
00083 );
00084 }
00085
00087 SdlSurfaceHolder():
00088 shared_ptr<SDL_Surface>(
00089 static_cast<SDL_Surface*>(NULL),
00090 Deleter()
00091 )
00092 {}
00093
00095 SdlSurfaceHolder(SDL_Surface *hangingSurf):
00096 shared_ptr<SDL_Surface>(
00097 hangingSurf,
00098 Deleter()
00099 )
00100 {}
00102 template <typename CustomDeleter>
00103 SdlSurfaceHolder(SDL_Surface *hangingSurf, CustomDeleter customDeleter):
00104 shared_ptr<SDL_Surface>(
00105 hangingSurf,
00106 customDeleter
00107 )
00108 {}
00109 ~SdlSurfaceHolder() {}
00110 };
00111
00113 class ManagerSdl{
00114 public:
00115
00116 ManagerSdl(){
00117
00118 clog << "INFO: SDL Init" << endl;
00119
00120 CHECKZ_SDL( SDL_Init(SDL_INIT_VIDEO) );
00121
00122 }
00123
00124 ~ManagerSdl(){
00125 clog << "INFO: SDL Cleanup" << endl;
00126 SDL_Quit();
00127 }
00128
00129 void setVideoMode(Integer newScreenXSize, Integer newScreenYSize){
00130 const SDL_VideoInfo *info = SDL_GetVideoInfo();
00131 CHECKZ_SDL( info == NULL );
00132
00133 clog << "INFO: Before SDL_SetVideoMode" << endl;
00134 CHECKNZ_SDL( SDL_SetVideoMode(
00135 newScreenXSize,
00136 newScreenYSize,
00137 info->vfmt->BitsPerPixel,
00138 SDL_RESIZABLE | SDL_ANYFORMAT
00139 ));
00140
00141 SdlSurfaceHolder screen = SdlSurfaceHolder::createWithNullDeleter(
00142 SDL_GetVideoSurface()
00143 );
00144 CHECKNZ_SDL( screen.get() );
00145 clog << "INFO: Video mode set: " << screen->w << "x" << screen->h <<
00146 " at " << Uint32(screen->format->BitsPerPixel) << " bpp" << endl;
00147
00148 SDL_ShowCursor(SDL_DISABLE);
00149 }
00150 };
00151
00153 SdlSurfaceHolder pictureToSdlSurface(Picture &src){
00154 if(src.get<std::string>("bm/pixel-format-type") != "rgb"){
00155 throw std::runtime_error(libnebular::Log::getWrongValueMsg(
00156 "\"bm/pixel-format-type\"", src.get<bool>("bm/pixel-format-type"), "== \"rgb\"",
00157 "Picture key", "Unsupported"
00158 ));
00159 }
00160 if(!src.get<bool>("bm/orient-top")){
00161 clog << "WARNING: " << libnebular::Log::getWrongValueMsg(
00162 "\"bm/orient-top\"", src.get<bool>("bm/orient-top"), "\"true\"",
00163 "Picture key", "Unsupported"
00164 ) << endl;
00165 }
00166 if(!src.get<bool>("bm/orient-left")){
00167 clog << "WARNING: " << libnebular::Log::getWrongValueMsg(
00168 "bm/orient-top", src.get<bool>("bm/orient-left"), "\"true\"",
00169 "Picture key", "Unsupported"
00170 ) << endl;
00171 }
00172
00173 SdlSurfaceHolder dest(
00174 SDL_CreateRGBSurface(
00175 0,
00176 src.get<Integer>("bm/x-size"),
00177 src.get<Integer>("bm/y-size"),
00178 src.get<Integer>("bm/bpp"),
00179 src.get<Integer>("bm/pixel-mask/r"),
00180 src.get<Integer>("bm/pixel-mask/g"),
00181 src.get<Integer>("bm/pixel-mask/b"),
00182 src.get<Integer>("bm/pixel-mask/a")
00183 )
00184 );
00185 CHECKZ_SDL( isEmpty(dest) );
00186
00187 const char *srcData = src.get<Blob>("bm/data").getDataReadOnly();
00188 char *destData = static_cast<char*>(dest->pixels);
00189 src.calculate<libnebular::PictureProps::PropCalcBmDataSize>();
00190 Integer srcPitchBits = (
00191 src.get<Integer>("calc/bm/scanline-pitch-bits")
00192 );
00193
00194 if(srcPitchBits % bitsPerByte != 0){
00195 throw std::runtime_error(libnebular::Log::getWrongValueMsg(
00196 "<scanline-pitch>", srcPitchBits, "\"srcPitchBits % bitsPerByte == 0\"",
00197 "calculated from Picture key", "Unsupported"
00198 ));
00199 }
00200 Integer srcPitch = srcPitchBits / bitsPerByte;
00201 Integer destPitch = dest->pitch;
00202 Integer srcBmYSize = src.get<Integer>("bm/y-size");
00203
00204 for(
00205 Integer y = 0;
00206 y < srcBmYSize;
00207 ++y
00208 ){
00209 std::copy(
00210 srcData,
00211 srcData+srcPitch,
00212 destData
00213 );
00214
00215 srcData += srcPitch;
00216 destData += destPitch;
00217 }
00218
00219 return dest;
00220 }
00221
00222 #endif // HAVE_SDL_SDL_H
00223
00224 #endif // SDL_UTILS_HPP_