diff --git a/CMakeLists.txt b/CMakeLists.txt index 3bd5edb..4c54390 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -114,14 +114,6 @@ SET(LIBRARY_SOURCES SDL2pp/Window.cc ) -IF(SDL2PP_WITH_TTF) - SET(LIBRARY_SOURCES - ${LIBRARY_SOURCES} - SDL2pp/SDLTTF.cc - SDL2pp/Font.cc - ) -ENDIF(SDL2PP_WITH_TTF) - SET(LIBRARY_HEADERS SDL2pp/AudioDevice.hh SDL2pp/AudioSpec.hh @@ -141,7 +133,13 @@ SET(LIBRARY_HEADERS SDL2pp/Window.hh ) +# optional sources IF(SDL2PP_WITH_TTF) + SET(LIBRARY_SOURCES + ${LIBRARY_SOURCES} + SDL2pp/SDLTTF.cc + SDL2pp/Font.cc + ) SET(LIBRARY_HEADERS ${LIBRARY_HEADERS} SDL2pp/SDLTTF.hh @@ -149,13 +147,24 @@ IF(SDL2PP_WITH_TTF) ) ENDIF(SDL2PP_WITH_TTF) +IF(SDL2PP_WITH_IMAGE) + SET(LIBRARY_SOURCES + ${LIBRARY_SOURCES} + SDL2pp/SDLImage.cc + ) + SET(LIBRARY_HEADERS + ${LIBRARY_HEADERS} + SDL2pp/SDLImage.hh + ) +ENDIF(SDL2PP_WITH_IMAGE) + IF(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR) - MESSAGE(STATUS "libSDL2pp standalone build") + MESSAGE(STATUS "libSDL2pp ${SDL2PP_VERSION} standalone build") # library ADD_LIBRARY(SDL2pp SHARED ${LIBRARY_SOURCES} ${LIBRARY_HEADERS}) TARGET_LINK_LIBRARIES(SDL2pp ${SDL2_ALL_LIBRARIES}) - SET_TARGET_PROPERTIES(SDL2pp PROPERTIES VERSION 2.0.0 SOVERSION 2) + SET_TARGET_PROPERTIES(SDL2pp PROPERTIES VERSION 3.0.0 SOVERSION 3) # examples and tests OPTION(SDL2PP_WITH_EXAMPLES "Build examples" ON) @@ -193,7 +202,7 @@ IF(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR) INSTALL(TARGETS SDL2pp LIBRARY DESTINATION lib) INSTALL(FILES ${PROJECT_BINARY_DIR}/sdl2pp.pc DESTINATION ${PKGCONFIGDIR}) ELSE(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR) - MESSAGE(STATUS "libSDL2pp bundled build") + MESSAGE(STATUS "libSDL2pp ${SDL2PP_VERSION} bundled build") # library ADD_LIBRARY(SDL2pp STATIC ${LIBRARY_SOURCES} ${LIBRARY_HEADERS}) diff --git a/README.md b/README.md index 0ade3d4..27c20e5 100644 --- a/README.md +++ b/README.md @@ -77,6 +77,9 @@ methods. These classes also support: ## Building ## +To build libSDL2pp, you need a compiler with C++11 support, for +example clang 3.4+ or gcc 4.8+. + Dependencies: * cmake * SDL2 diff --git a/SDL2pp/Exception.cc b/SDL2pp/Exception.cc index 546ade5..463415c 100644 --- a/SDL2pp/Exception.cc +++ b/SDL2pp/Exception.cc @@ -36,7 +36,7 @@ const char* Exception::what() const noexcept { } const char* Exception::GetSDLError() const noexcept { - return sdl_error_; + return sdl_error_.c_str(); } } // namespace SDL2pp diff --git a/SDL2pp/Exception.hh b/SDL2pp/Exception.hh index e7ea7b1..5151f1a 100644 --- a/SDL2pp/Exception.hh +++ b/SDL2pp/Exception.hh @@ -22,6 +22,7 @@ #ifndef SDL2PP_EXCEPTION_HH #define SDL2PP_EXCEPTION_HH +#include #include namespace SDL2pp { @@ -42,6 +43,13 @@ namespace SDL2pp { /// what() usually contains a name of SDL2 function which failed, /// e.g. "SDL_Init() failed" /// +/// Note: this Exception object is used to report errors from +/// SDL2 satellite libraries (SDL_image, SDL_mixer, SDL_ttf) +/// as well. Though they use their own error handling functions +/// (IMG_GetError, Mix_GetError, TTF_GetError), those are (currently) +/// just macros pointing to SDL_GetError. We currently rely on that. +/// If that changes, we'll need a hierarchy of specific exceptions. +/// /// Usage example: /// \code /// { @@ -61,7 +69,7 @@ namespace SDL2pp { class Exception : public std::exception { private: const char* what_; ///< User-specified message - const char* sdl_error_; ///< SDL error string + std::string sdl_error_; ///< SDL error string public: //////////////////////////////////////////////////////////// @@ -72,7 +80,6 @@ public: //////////////////////////////////////////////////////////// Exception(const char* what = ""); - //////////////////////////////////////////////////////////// /// \brief Destructor /// diff --git a/SDL2pp/Renderer.cc b/SDL2pp/Renderer.cc index 7c2ccef..5e14cac 100644 --- a/SDL2pp/Renderer.cc +++ b/SDL2pp/Renderer.cc @@ -30,6 +30,9 @@ namespace SDL2pp { +Renderer::Renderer(SDL_Renderer* renderer) : renderer_(renderer) { +} + Renderer::Renderer(Window& window, int index, Uint32 flags) { if ((renderer_ = SDL_CreateRenderer(window.Get(), index, flags)) == nullptr) throw Exception("SDL_CreateRenderer failed"); diff --git a/SDL2pp/Renderer.hh b/SDL2pp/Renderer.hh index 80bfd9a..1d0b9bc 100644 --- a/SDL2pp/Renderer.hh +++ b/SDL2pp/Renderer.hh @@ -51,6 +51,14 @@ private: SDL_Renderer* renderer_; ///< Contained SDL_Renderer structure public: + //////////////////////////////////////////////////////////// + /// \brief Construct from existing SDL_Renderer structure + /// + /// \param renderer Existing SDL_Renderer to manage + /// + //////////////////////////////////////////////////////////// + Renderer(SDL_Renderer* renderer); + //////////////////////////////////////////////////////////// /// \brief Create renderer /// diff --git a/SDL2pp/SDL2pp.hh b/SDL2pp/SDL2pp.hh index 0d41c89..c383cb2 100644 --- a/SDL2pp/SDL2pp.hh +++ b/SDL2pp/SDL2pp.hh @@ -95,15 +95,25 @@ #include #include +//////////////////////////////////////////////////////////// +/// \defgroup ttf SDL_ttf +/// +/// \brief Text rendering throught SDL_ttf library +/// +//////////////////////////////////////////////////////////// #ifdef SDL2PP_WITH_TTF - //////////////////////////////////////////////////////////// - /// \defgroup ttf SDL_ttf - /// - /// \brief Text rendering throught SDL_ttf library - /// - //////////////////////////////////////////////////////////// # include # include #endif +//////////////////////////////////////////////////////////// +/// \defgroup image SDL_image +/// +/// \brief Functions that are specific to SDL_image library +/// +//////////////////////////////////////////////////////////// +#ifdef SDL2PP_WITH_IMAGE +# include +#endif + #endif diff --git a/SDL2pp/SDLImage.cc b/SDL2pp/SDLImage.cc new file mode 100644 index 0000000..f2e9c66 --- /dev/null +++ b/SDL2pp/SDLImage.cc @@ -0,0 +1,49 @@ +/* + libSDL2pp - C++11 bindings/wrapper for SDL2 + Copyright (C) 2014 Dmitry Marakasov + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +#include + +#include +#include + +namespace SDL2pp { + +SDLImage::SDLImage(int flags) { + if ((IMG_Init(flags) & flags) != flags) + throw Exception("IMG_Init failed"); +} + +SDLImage::~SDLImage() { + IMG_Quit(); +} + +int SDLImage::InitMore(int flags) { + int ret; + if (((ret = IMG_Init(flags)) & flags) != flags) + throw Exception("IMG_Init failed"); + return ret; +} + +int SDLImage::GetInitFlags() { + return IMG_Init(0); +} + +} diff --git a/SDL2pp/SDLImage.hh b/SDL2pp/SDLImage.hh new file mode 100644 index 0000000..1d8e3cc --- /dev/null +++ b/SDL2pp/SDLImage.hh @@ -0,0 +1,106 @@ +/* + libSDL2pp - C++11 bindings/wrapper for SDL2 + Copyright (C) 2014 Dmitry Marakasov + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef SDL2PP_SDLIMAGE_HH +#define SDL2PP_SDLIMAGE_HH + +namespace SDL2pp { + +//////////////////////////////////////////////////////////// +/// \brief Object taking care of SDL_image library (de-)initialization +/// +/// \ingroup image +/// +/// \headerfile SDL2pp/SDLImage.hh +/// +/// Though it's possible to use SDL_image without initializing it, +/// library provide initialization/deinitialization functions to +/// be able to preload libraries for specific file format support +/// (png, jpeg or tiff) beforehand. In SDL2pp, this is handled by +/// this class. +/// +/// Usage example: +/// \code +/// int main() { +/// SDL2pp::SDL sdl(SDL_INIT_VIDEO); +/// SDL2pp::SDLImage image(IMG_INIT_PNG); +/// +/// // use SDL_image functions +/// SDL2pp::Texture t("/path/to/file.png"); +/// +/// // SDL_image library is automatically deinitialized before exit +/// return 0; +/// } +/// \endcode +/// +//////////////////////////////////////////////////////////// +class SDLImage { +public: + //////////////////////////////////////////////////////////// + /// \brief Initializes SDL_image library + /// + /// \param flags Flags to pass to IMG_Init() + /// + /// \throws SDL2pp::Exception + /// + /// \see https://www.libsdl.org/projects/SDL_image/docs/SDL_image.html#SEC8 + /// + //////////////////////////////////////////////////////////// + SDLImage(int flags); + + //////////////////////////////////////////////////////////// + /// \brief Destructor, deinitializes SDL_image library + /// + /// \see https://www.libsdl.org/projects/SDL_image/docs/SDL_image.html#SEC9 + /// + //////////////////////////////////////////////////////////// + virtual ~SDLImage(); + + //////////////////////////////////////////////////////////// + /// \brief Try to init more SDL_image formats + /// + /// \param flags Flags to pass to IMG_Init() + /// + /// \throws SDL2pp::Exception + /// + /// \see https://www.libsdl.org/projects/SDL_image/docs/SDL_image.html#SEC8 + /// + //////////////////////////////////////////////////////////// + int InitMore(int flags); + + //////////////////////////////////////////////////////////// + /// \brief Get mask of initialized SDL_image formats + /// + /// \see https://www.libsdl.org/projects/SDL_image/docs/SDL_image.html#SEC8 + /// + //////////////////////////////////////////////////////////// + int GetInitFlags(); + + // Deleted copy/move constructors and assignments + SDLImage(const SDLImage& other) = delete; + SDLImage(SDLImage&& other) = delete; + SDLImage& operator=(const SDLImage& other) = delete; + SDLImage& operator=(SDLImage&& other) = delete; +}; + +} + +#endif diff --git a/SDL2pp/Surface.hh b/SDL2pp/Surface.hh index 80851bf..5cdcb89 100644 --- a/SDL2pp/Surface.hh +++ b/SDL2pp/Surface.hh @@ -148,16 +148,15 @@ public: const SDL_PixelFormat& GetFormat() const; }; -private: +public: //////////////////////////////////////////////////////////// - /// \brief Create surface taking existing SDL_surface structure + /// \brief Construct from existing SDL_Surface structure /// - /// \param surface Existing SDL_surface to manage + /// \param surface Existing SDL_Surface to manage /// //////////////////////////////////////////////////////////// Surface(SDL_Surface* surface); -public: //////////////////////////////////////////////////////////// /// \brief Create RGB surface /// diff --git a/SDL2pp/Texture.cc b/SDL2pp/Texture.cc index 099da8e..2a5912e 100644 --- a/SDL2pp/Texture.cc +++ b/SDL2pp/Texture.cc @@ -40,6 +40,9 @@ namespace SDL2pp { +Texture::Texture(SDL_Texture* texture) : texture_(texture) { +} + Texture::Texture(Renderer& renderer, Uint32 format, int access, int w, int h) { if ((texture_ = SDL_CreateTexture(renderer.Get(), format, access, w, h)) == nullptr) throw Exception("SDL_CreateTexture failed"); @@ -47,12 +50,13 @@ Texture::Texture(Renderer& renderer, Uint32 format, int access, int w, int h) { #ifdef SDL2PP_WITH_IMAGE Texture::Texture(Renderer& renderer, RWops& rwops) { - texture_ = IMG_LoadTexture_RW(renderer.Get(), rwops.Get(), 0); + if ((texture_ = IMG_LoadTexture_RW(renderer.Get(), rwops.Get(), 0)) == nullptr) + throw Exception("IMG_LoadTexture_RW failed"); } Texture::Texture(Renderer& renderer, const std::string& path) { - RWops rwops = RWops::FromFile(path); - texture_ = IMG_LoadTexture_RW(renderer.Get(), rwops.Get(), 0); + if ((texture_ = IMG_LoadTexture(renderer.Get(), path.c_str())) == nullptr) + throw Exception("IMG_LoadTexture failed"); } #endif diff --git a/SDL2pp/Texture.hh b/SDL2pp/Texture.hh index cb2a7ad..84b32d2 100644 --- a/SDL2pp/Texture.hh +++ b/SDL2pp/Texture.hh @@ -50,7 +50,7 @@ class Surface; //////////////////////////////////////////////////////////// class Texture { private: - SDL_Texture* texture_; ///< SDL2 texture pointer + SDL_Texture* texture_; ///< Contained SDL_Texture structure public: //////////////////////////////////////////////////////////// @@ -104,7 +104,7 @@ public: /// /// \throws STL2pp::Exception /// - /// \see http://wiki.libsdl.org/SDL_LockAudioDevice + /// \see http://wiki.libsdl.org/SDL_LockTexture /// //////////////////////////////////////////////////////////// LockHandle(Texture* texture, const Optional& rect); @@ -126,7 +126,7 @@ public: /// \details /// Releases the lock /// - /// \see http://wiki.libsdl.org/SDL_UnlockAudioDevice + /// \see http://wiki.libsdl.org/SDL_UnlockTexture /// //////////////////////////////////////////////////////////// ~LockHandle(); @@ -134,7 +134,7 @@ public: //////////////////////////////////////////////////////////// /// \brief Move constructor /// - /// \param other SDL2pp::AudioDevice::LockHandle to move data from + /// \param other SDL2pp::Texture::LockHandle to move data from /// //////////////////////////////////////////////////////////// LockHandle(LockHandle&& other) noexcept; @@ -142,7 +142,7 @@ public: //////////////////////////////////////////////////////////// /// \brief Move assignment operator /// - /// \param other SDL2pp::AudioDevice::LockHandle to move data from + /// \param other SDL2pp::Texture::LockHandle to move data from /// /// \returns Reference to self /// @@ -172,6 +172,14 @@ public: }; public: + //////////////////////////////////////////////////////////// + /// \brief Construct from existing SDL_Texture structure + /// + /// \param texture Existing SDL_Texture to manage + /// + //////////////////////////////////////////////////////////// + Texture(SDL_Texture* texture); + //////////////////////////////////////////////////////////// /// \brief Create empty texture /// @@ -195,6 +203,8 @@ public: /// \param renderer Rendering context to create texture for /// \param rwops RWops used to access an image file /// + /// \throws SDL2pp::Exception + /// //////////////////////////////////////////////////////////// Texture(Renderer& renderer, RWops& rwops); @@ -204,6 +214,8 @@ public: /// \param renderer Rendering context to create texture for /// \param filename Path to an image file /// + /// \throws SDL2pp::Exception + /// //////////////////////////////////////////////////////////// Texture(Renderer& renderer, const std::string& filename); #endif @@ -224,6 +236,8 @@ public: //////////////////////////////////////////////////////////// /// \brief Destructor /// + /// \see http://wiki.libsdl.org/SDL_DestroyTexture + /// //////////////////////////////////////////////////////////// virtual ~Texture(); diff --git a/SDL2pp/Window.cc b/SDL2pp/Window.cc index 2073941..71ef909 100644 --- a/SDL2pp/Window.cc +++ b/SDL2pp/Window.cc @@ -26,6 +26,9 @@ namespace SDL2pp { +Window::Window(SDL_Window* window) : window_(window) { +} + Window::Window(const std::string& title, int x, int y, int w, int h, Uint32 flags) { if ((window_ = SDL_CreateWindow(title.c_str(), x, y, w, h, flags)) == nullptr) throw Exception("SDL_CreateWindow failed"); @@ -50,6 +53,10 @@ Window& Window::operator=(Window&& other) noexcept { return *this; } +SDL_Window* Window::Get() const { + return window_; +} + Point Window::GetSize() const { int w, h; SDL_GetWindowSize(window_, &w, &h); @@ -72,10 +79,6 @@ void Window::SetTitle(const std::string& title) { SDL_SetWindowTitle(window_, title.c_str()); } -SDL_Window* Window::Get() const { - return window_; -} - void Window::Maximize() { SDL_MaximizeWindow(window_); } diff --git a/SDL2pp/Window.hh b/SDL2pp/Window.hh index 3b06c75..d1a9a79 100644 --- a/SDL2pp/Window.hh +++ b/SDL2pp/Window.hh @@ -64,6 +64,14 @@ private: SDL_Window* window_; ///< Contained SDL2_Window structure public: + //////////////////////////////////////////////////////////// + /// \brief Construct from existing SDL_Window structure + /// + /// \param window Existing SDL_Window to manage + /// + //////////////////////////////////////////////////////////// + Window(SDL_Window* window); + //////////////////////////////////////////////////////////// /// \brief Create window with specified title and fimensions /// @@ -111,6 +119,14 @@ public: Window(const Window& other) = delete; Window& operator=(const Window& other) = delete; + //////////////////////////////////////////////////////////// + /// \brief Get pointer to contained SDL_Window structure + /// + /// \returns Pointer to SDL_Window structure + /// + //////////////////////////////////////////////////////////// + SDL_Window* Get() const; + //////////////////////////////////////////////////////////// /// \brief Get dimensions of the window /// @@ -152,14 +168,6 @@ public: //////////////////////////////////////////////////////////// void SetTitle(const std::string& title); - //////////////////////////////////////////////////////////// - /// \brief Get pointer to contained SDL_Window structure - /// - /// \returns Pointer to SDL_Window structure - /// - //////////////////////////////////////////////////////////// - SDL_Window* Get() const; - //////////////////////////////////////////////////////////// /// \brief Make a window as large as possible /// diff --git a/examples/image.cc b/examples/image.cc index 377ef19..c47eeb1 100644 --- a/examples/image.cc +++ b/examples/image.cc @@ -22,8 +22,10 @@ #include #include +#include #include +#include #include #include #include @@ -34,6 +36,7 @@ using namespace SDL2pp; int Run() { SDL sdl(SDL_INIT_VIDEO); + SDLImage image(IMG_INIT_PNG); // optional Window window("libSDL2pp demo: loading", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 480, SDL_WINDOW_RESIZABLE); Renderer render(window, -1, SDL_RENDERER_ACCELERATED); diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index d76df00..d9b1af4 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -3,6 +3,7 @@ SET(CLI_TESTS test_pointrect test_rwops test_optional + test_error ) # tests which test graphics functionality and thus requre working diff --git a/tests/test_error.cc b/tests/test_error.cc new file mode 100644 index 0000000..46d9dd5 --- /dev/null +++ b/tests/test_error.cc @@ -0,0 +1,18 @@ +#include + +#include + +#include "testing.h" + +using namespace SDL2pp; + +BEGIN_TEST() + SDL_SetError("foo"); + + try { + throw Exception(""); + } catch (SDL2pp::Exception& e) { + SDL_SetError("bar"); + EXPECT_EQUAL((std::string)e.GetSDLError(), "foo"); + } +END_TEST()