#ifndef WC3RE_RENDER_SDLUTIL_HH__ #define WC3RE_RENDER_SDLUTIL_HH__ #include #include #include #include #include "exceptions.hh" namespace render { class SDLException : public Exception { public: SDLException() : Exception(SDL_GetError()) { } std::string toString() const override { return "SDLException: " + msg_; } }; class TTFException : public Exception { public: TTFException() : Exception(TTF_GetError()) { } std::string toString() const override { return "TTFException: " + msg_; } }; // Some helpers to C++11-ify SDL struct SDLSurfaceDeleter { void operator()(SDL_Surface *ptr) const { SDL_FreeSurface(ptr); } }; using SDLSurfaceUPtr = std::unique_ptr; struct SDLWindowDeleter { void operator()(SDL_Window *ptr) const { SDL_DestroyWindow(ptr); } }; using SDLWindowUPtr = std::unique_ptr; struct TTFFontDeleter { void operator()(TTF_Font* font) const { TTF_CloseFont(font); } }; using TTFFontUPtr = std::unique_ptr; class SDLSurfaceScopedLock { public: SDLSurfaceScopedLock(SDL_Surface *surf) : surf_(surf) { if (SDL_MUSTLOCK(surf_)) if (SDL_LockSurface(surf_) != 0) throw SDLException{}; } SDLSurfaceScopedLock(SDLSurfaceUPtr& surf) : surf_(surf.get()) { if (SDL_MUSTLOCK(surf_)) if (SDL_LockSurface(surf_) != 0) throw SDLException{}; } SDLSurfaceScopedLock(SDLSurfaceScopedLock const& copy) = delete; SDLSurfaceScopedLock& operator=(SDLSurfaceScopedLock const& copy) = delete; ~SDLSurfaceScopedLock() { if (surf_ && SDL_MUSTLOCK(surf_)) SDL_UnlockSurface(surf_); } void unlock() { if (surf_ && SDL_MUSTLOCK(surf_)) SDL_UnlockSurface(surf_); surf_ = nullptr; } private: SDL_Surface *surf_; }; static bool operator==(SDL_Color const& a, SDL_Color const& b) { return ((a.r == b.r) && (a.g == b.g) && (a.b == b.b) && (a.a == b.a)); } static bool operator!=(SDL_Color const& a, SDL_Color const& b) { return ((a.r != b.r) || (a.g != b.g) || (a.b != b.b) || (a.a != b.a)); } // RAII wrapper for SDL_Init class SDLInit { public: SDLInit(uint32_t flags = SDL_INIT_VIDEO) { if (SDL_Init(flags) < 0) throw SDLException{}; } SDLInit(SDLInit const& copy) = delete; SDLInit& operator=(SDLInit const& copy) = delete; ~SDLInit() { SDL_Quit(); } }; // RAII wrapper for TTF_Init class TTFInit { public: TTFInit() { if (TTF_Init() < 0) throw TTFException{}; } TTFInit(TTFInit const& copy) = delete; TTFInit& operator=(TTFInit const& copy) = delete; ~TTFInit() { TTF_Quit(); } }; // RAII wrapper for SDL_GLContext class SDLGLContext { public: SDLGLContext(SDL_Window *win) : context_(SDL_GL_CreateContext(win)) { if (!context_) throw SDLException{}; } SDLGLContext() : context_(nullptr) { } SDLGLContext(SDLGLContext const& copy) = delete; SDLGLContext& operator=(SDLGLContext const& copy) = delete; SDLGLContext(SDLGLContext && move): context_(move.context_) { move.context_ = nullptr; } SDLGLContext& operator=(SDLGLContext && move) { if (context_) SDL_GL_DeleteContext(context_); context_ = move.context_; move.context_ = nullptr; return *this; } ~SDLGLContext() { if (context_) SDL_GL_DeleteContext(context_); } operator SDL_GLContext() const { return context_; } private: SDL_GLContext context_; }; } #endif