diff --git a/CMakeLists.txt b/CMakeLists.txt index a595c43..83a23c5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -99,6 +99,8 @@ SET(LIBRARY_SOURCES SDL2pp/Renderer.cc SDL2pp/SDL.cc SDL2pp/SDLImage.cc + SDL2pp/Surface.cc + SDL2pp/SurfaceLock.cc SDL2pp/Texture.cc SDL2pp/TextureLock.cc SDL2pp/Wav.cc @@ -119,6 +121,7 @@ SET(LIBRARY_HEADERS SDL2pp/SDL2pp.hh SDL2pp/SDLImage.hh SDL2pp/StreamRWops.hh + SDL2pp/Surface.hh SDL2pp/Texture.hh SDL2pp/Wav.hh SDL2pp/Window.hh diff --git a/SDL2pp/Point.cc b/SDL2pp/Point.cc index 07311db..b2e7cdb 100644 --- a/SDL2pp/Point.cc +++ b/SDL2pp/Point.cc @@ -30,6 +30,11 @@ Point::Point() { y = 0; } +Point::Point(const SDL_Point& point) { + x = point.x; + y = point.y; +} + Point::Point(int nx, int ny) { x = nx; y = ny; diff --git a/SDL2pp/Point.hh b/SDL2pp/Point.hh index d98e65b..98bcaaf 100644 --- a/SDL2pp/Point.hh +++ b/SDL2pp/Point.hh @@ -54,6 +54,14 @@ public: //////////////////////////////////////////////////////////// Point(); + //////////////////////////////////////////////////////////// + /// \brief Construct a point from existing SDL_Point + /// + /// \param point Existing SDL_Point + /// + //////////////////////////////////////////////////////////// + Point(const SDL_Point& point); + //////////////////////////////////////////////////////////// /// \brief Construct the point from given coordinates /// diff --git a/SDL2pp/Rect.cc b/SDL2pp/Rect.cc index aef68d3..9b739e9 100644 --- a/SDL2pp/Rect.cc +++ b/SDL2pp/Rect.cc @@ -34,6 +34,13 @@ Rect::Rect() { h = 0; } +Rect::Rect(const SDL_Rect& rect) { + x = rect.x; + y = rect.y; + w = rect.w; + h = rect.h; +} + Rect::Rect(int nx, int ny, int nw, int nh) { x = nx; y = ny; diff --git a/SDL2pp/Rect.hh b/SDL2pp/Rect.hh index 7b7049d..4439396 100644 --- a/SDL2pp/Rect.hh +++ b/SDL2pp/Rect.hh @@ -58,6 +58,14 @@ public: //////////////////////////////////////////////////////////// Rect(); + //////////////////////////////////////////////////////////// + /// \brief Construct a rect from existing SDL_Rect + /// + /// \param rect Existing SDL_Rect + /// + //////////////////////////////////////////////////////////// + Rect(const SDL_Rect& rect); + //////////////////////////////////////////////////////////// /// \brief Construct the rect from given corner coordinates, width and height /// diff --git a/SDL2pp/Surface.cc b/SDL2pp/Surface.cc new file mode 100644 index 0000000..789a0e0 --- /dev/null +++ b/SDL2pp/Surface.cc @@ -0,0 +1,196 @@ +/* + 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 +#ifdef SDL2PP_WITH_IMAGE +# include +#endif + +#include +#include +#ifdef SDL2PP_WITH_IMAGE +# include +#endif + +namespace SDL2pp { + +Surface::Surface(SDL_Surface* surface) : surface_(surface) { +} + +Surface::Surface(Uint32 flags, int width, int height, int depth, Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask) { + if ((surface_ = SDL_CreateRGBSurface(flags, width, height, depth, Rmask, Gmask, Bmask, Amask)) == nullptr) + throw Exception("SDL_CreateRGBSurface failed"); +} + +Surface::Surface(void* pixels, int width, int height, int depth, int pitch, Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask) { + if ((surface_ = SDL_CreateRGBSurfaceFrom(pixels, width, height, depth, pitch, Rmask, Gmask, Bmask, Amask)) == nullptr) + throw Exception("SDL_CreateRGBSurfaceFrom failed"); +} + +#ifdef SDL2PP_WITH_IMAGE +Surface::Surface(RWops& rwops) { + if ((surface_ = IMG_Load_RW(rwops.Get(), 0)) == nullptr) + throw Exception("IMG_Load_RW failed"); +} + +Surface::Surface(const std::string& path) { + if ((surface_ = IMG_Load(path.c_str())) == nullptr) + throw Exception("IMG_Load failed"); +} +#endif + +Surface::~Surface() { + if (surface_ != nullptr) + SDL_FreeSurface(surface_); +} + +Surface::Surface(Surface&& other) noexcept : surface_(other.surface_) { + other.surface_ = nullptr; +} + +Surface& Surface::operator=(Surface&& other) noexcept { + if (&other == this) + return *this; + if (surface_ != nullptr) + SDL_FreeSurface(surface_); + surface_ = other.surface_; + other.surface_ = nullptr; + return *this; +} + +SDL_Surface* Surface::Get() const { + return surface_; +} + +Surface Surface::Convert(const SDL_PixelFormat& format) { + SDL_Surface* surface = SDL_ConvertSurface(surface_, &format, 0); + if (surface == nullptr) + throw Exception("SDL_ConvertPixels failed"); + return surface; +} + +Surface Surface::Convert(Uint32 pixel_format) { + SDL_Surface* surface = SDL_ConvertSurfaceFormat(surface_, pixel_format, 0); + if (surface == nullptr) + throw Exception("SDL_ConvertPixels failed"); + return surface; +} + +void Surface::Blit(const Optional& srcrect, Surface& dst, const Rect& dstrect) { + SDL_Rect tmpdstrect = dstrect; // 4th argument is non-const; does it modify rect? + if (SDL_BlitSurface(surface_, srcrect ? &*srcrect : nullptr, dst.Get(), &tmpdstrect) != 0) + throw Exception("SDL_BlitSurface failed"); +} + +void Surface::BlitScaled(const Optional& srcrect, Surface& dst, const Optional& dstrect) { + SDL_Rect tmpdstrect; // 4th argument is non-const; does it modify rect? + if (dstrect) + tmpdstrect = *dstrect; + if (SDL_BlitScaled(surface_, srcrect ? &*srcrect : nullptr, dst.Get(), dstrect ? &tmpdstrect : nullptr) != 0) + throw Exception("SDL_BlitScaled failed"); +} + +Surface::LockHandle Surface::Lock() { + return LockHandle(this); +} + +Rect Surface::GetClipRect() const { + SDL_Rect rect; + SDL_GetClipRect(surface_, &rect); + return Rect(rect); +} + +Uint32 Surface::GetColorKey() const { + Uint32 key; + if (SDL_GetColorKey(surface_, &key) != 0) + throw Exception("SDL_GetColorKey failed"); + return key; +} + +Uint8 Surface::GetAlphaMod() const { + Uint8 alpha; + if (SDL_GetSurfaceAlphaMod(surface_, &alpha) != 0) + throw Exception("SDL_GetSurfaceAlphaMod failed"); + return alpha; +} + +SDL_BlendMode Surface::GetBlendMode() const { + SDL_BlendMode blendMode; + if (SDL_GetSurfaceBlendMode(surface_, &blendMode) != 0) + throw Exception("SDL_GetSurfaceBlendMode failed"); + return blendMode; +} + +void Surface::GetColorMod(Uint8& r, Uint8& g, Uint8& b) const { + if (SDL_GetSurfaceColorMod(surface_, &r, &g, &b) != 0) + throw Exception("SDL_GetSurfaceColorMod failed"); +} + +void Surface::SetClipRect(const Optional& rect) { + if (SDL_SetClipRect(surface_, rect ? &*rect : nullptr) != 0) + throw Exception("SDL_SetClipRect failed"); +} + +void Surface::SetColorKey(int flag, Uint32 key) { + if (SDL_SetColorKey(surface_, flag, key) != 0) + throw Exception("SDL_SetColorKey failed"); +} + +void Surface::SetAlphaMod(Uint8 alpha) { + if (SDL_SetSurfaceAlphaMod(surface_, alpha) != 0) + throw Exception("SDL_SetSurfaceAlphaMod failed"); +} + +void Surface::SetBlendMode(SDL_BlendMode blendMode) { + if (SDL_SetSurfaceBlendMode(surface_, blendMode) != 0) + throw Exception("SDL_SetSurfaceBlendMode failed"); +} + +void Surface::SetColorMod(Uint8 r, Uint8 g, Uint8 b) { + if (SDL_SetSurfaceColorMod(surface_, r, g, b) != 0) + throw Exception("SDL_SetSurfaceColorMod failed"); +} + +void Surface::SetRLE(int flag) { + if (SDL_SetSurfaceRLE(surface_, flag) != 0) + throw Exception("SDL_SetSurfaceRLE failed"); +} + +void Surface::FillRect(const Optional& rect, Uint32 color) { + if (SDL_FillRect(surface_, rect ? &*rect : nullptr, color) != 0) + throw Exception("SDL_FillRect failed"); +} + +void Surface::FillRects(const Rect* rects, int count, Uint32 color) { + std::vector sdl_rects; + sdl_rects.reserve(count); + for (const Rect* r = rects; r != rects + count; ++r) + sdl_rects.emplace_back(*r); + + if (SDL_FillRects(surface_, sdl_rects.data(), sdl_rects.size(), color) != 0) + throw Exception("SDL_FillRects failed"); +} + +} diff --git a/SDL2pp/Surface.hh b/SDL2pp/Surface.hh new file mode 100644 index 0000000..80851bf --- /dev/null +++ b/SDL2pp/Surface.hh @@ -0,0 +1,487 @@ +/* + 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_SURFACE_HH +#define SDL2PP_SURFACE_HH + +#include +#include + +#include +#include +#include + +struct SDL_Surface; +struct SDL_PixelFormat; + +namespace SDL2pp { + +class RWops; + +//////////////////////////////////////////////////////////// +/// \brief Image stored in system memory with direct access +/// to pixel data +/// +/// \ingroup rendering +/// +/// \headerfile SDL2pp/Surface.hh +/// +/// \see http://wiki.libsdl.org/SDL_Surface +/// +//////////////////////////////////////////////////////////// +class Surface { +private: + SDL_Surface* surface_; ///< Contained SDL_Texture structure + +public: + //////////////////////////////////////////////////////////// + /// \brief SDL2pp::Surface lock + /// \ingroup rendering + /// + /// \details + /// For direct pixel access, SDL surface may need to be locked. + /// This class represents the lock and controls its lifetime + /// as the lock is released as soon as LockHandle is destroyed. + /// + //////////////////////////////////////////////////////////// + class LockHandle { + friend class Surface; + private: + Surface* surface_; ///< SDL2pp::Surface this lock belongs to + + private: + //////////////////////////////////////////////////////////// + /// \brief Create lock for specific SDL2pp::Texture + /// + /// \throws STL2pp::Exception + /// + /// \see http://wiki.libsdl.org/SDL_LockSurface + /// + //////////////////////////////////////////////////////////// + LockHandle(Surface* surface); + + public: + //////////////////////////////////////////////////////////// + /// \brief Create no-op lock + /// + /// \details + /// This may be initialized with real lock later with move + /// assignment operator + /// + //////////////////////////////////////////////////////////// + LockHandle(); + + //////////////////////////////////////////////////////////// + /// \brief Destructor + /// + /// \details + /// Releases the lock + /// + /// \see http://wiki.libsdl.org/SDL_UnlockSurface + /// + //////////////////////////////////////////////////////////// + ~LockHandle(); + + //////////////////////////////////////////////////////////// + /// \brief Move constructor + /// + /// \param other SDL2pp::Surface::LockHandle to move data from + /// + //////////////////////////////////////////////////////////// + LockHandle(LockHandle&& other) noexcept; + + //////////////////////////////////////////////////////////// + /// \brief Move assignment operator + /// + /// \param other SDL2pp::Surface::LockHandle to move data from + /// + /// \returns Reference to self + /// + //////////////////////////////////////////////////////////// + LockHandle& operator=(LockHandle&& other) noexcept; + + // Deleted copy constructor and assignment + LockHandle(const LockHandle& other) = delete; + LockHandle& operator=(const LockHandle& other) = delete; + + //////////////////////////////////////////////////////////// + /// \brief Get pointer to raw pixel data of locked region + /// + /// \returns Pointer to raw pixel data of locked region + /// + //////////////////////////////////////////////////////////// + void* GetPixels() const; + + //////////////////////////////////////////////////////////// + /// \brief Get pitch of locked pixel data + /// + /// \returns Number of bytes in a row of pixel data, including + /// padding between lines + /// + //////////////////////////////////////////////////////////// + int GetPitch() const; + + //////////////////////////////////////////////////////////// + /// \brief Get pixel format of the surface + /// + /// \returns Format of the pixels stored in the surface + /// + //////////////////////////////////////////////////////////// + const SDL_PixelFormat& GetFormat() const; + }; + +private: + //////////////////////////////////////////////////////////// + /// \brief Create surface taking existing SDL_surface structure + /// + /// \param surface Existing SDL_surface to manage + /// + //////////////////////////////////////////////////////////// + Surface(SDL_Surface* surface); + +public: + //////////////////////////////////////////////////////////// + /// \brief Create RGB surface + /// + /// \param flags Unused and should be set to 0 + /// \param width Width of the surface + /// \param height Height of the surface + /// \param depth Depth of the surface in bits + /// \param Rmask Red mask for the pixels + /// \param Gmask Green mask for the pixels + /// \param Bmask Blue mask for the pixels + /// \param Amask Alpha mask for the pixels + /// + /// \throws SDL2pp::Exception + /// + /// \see http://wiki.libsdl.org/SDL_CreateRGBSurface + /// + //////////////////////////////////////////////////////////// + Surface(Uint32 flags, int width, int height, int depth, Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask); + + //////////////////////////////////////////////////////////// + /// \brief Create RGB surface with existing pixel data + /// + /// \param pixels Pointer to existing pixel data + /// \param width Width of the surface + /// \param height Height of the surface + /// \param depth depth of the surface in bits + /// \param pitch Number of bytes in a row of pixel data, including padding between lines + /// \param Rmask Red mask for the pixels + /// \param Gmask Green mask for the pixels + /// \param Bmask Blue mask for the pixels + /// \param Amask Alpha mask for the pixels + /// + /// \throws SDL2pp::Exception + /// + /// \see http://wiki.libsdl.org/SDL_CreateRGBSurfaceFrom + /// + //////////////////////////////////////////////////////////// + Surface(void* pixels, int width, int height, int depth, int pitch, Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask); + +#ifdef SDL2PP_WITH_IMAGE + //////////////////////////////////////////////////////////// + /// \brief Create surface loading it via RWops + /// + /// \param rwops RWops used to access an image file + /// + //////////////////////////////////////////////////////////// + Surface(RWops& rwops); + + //////////////////////////////////////////////////////////// + /// \brief Create surface loading it from file + /// + /// \param filename Path to an image file + /// + //////////////////////////////////////////////////////////// + Surface(const std::string& filename); +#endif + + //////////////////////////////////////////////////////////// + /// \brief Destructor + /// + /// \see http://wiki.libsdl.org/SDL_FreeSurface + /// + //////////////////////////////////////////////////////////// + virtual ~Surface(); + + //////////////////////////////////////////////////////////// + /// \brief Move constructor + /// + /// \param other SDL2pp::Surface object to move data from + /// + //////////////////////////////////////////////////////////// + Surface(Surface&& other) noexcept; + + //////////////////////////////////////////////////////////// + /// \brief Move assignment + /// + /// \param other SDL2pp::Surface object to move data from + /// + /// \returns Reference to self + /// + //////////////////////////////////////////////////////////// + Surface& operator=(Surface&& other) noexcept; + + // Deleted copy constructor and assignment + Surface(const Surface&) = delete; + Surface& operator=(const Surface&) = delete; + + //////////////////////////////////////////////////////////// + /// \brief Get pointer to contained SDL_Surface structure + /// + /// \returns Pointer to contained SDL_Surface structure + /// + //////////////////////////////////////////////////////////// + SDL_Surface* Get() const; + + //////////////////////////////////////////////////////////// + /// \brief Copy an existing surface into a new one that is + /// optimized for blitting to a surface of a specified pixel format + /// + /// \param format SDL_PixelFormat structure that the new surface is optimized for + /// + /// \throws SDL2pp::Exception + /// + /// \see http://wiki.libsdl.org/SDL_ConvertSurface + /// + //////////////////////////////////////////////////////////// + Surface Convert(const SDL_PixelFormat& format); + + //////////////////////////////////////////////////////////// + /// \brief Copy an existing surface to a new surface of the specified format + /// + /// \param pixel_format One of the enumerated values in SDL_PixelFormatEnum + /// + /// \throws SDL2pp::Exception + /// + /// \see http://wiki.libsdl.org/SDL_PixelFormatEnum + /// \see http://wiki.libsdl.org/SDL_ConvertSurfaceFormat + /// + //////////////////////////////////////////////////////////// + Surface Convert(Uint32 pixel_format); + + //////////////////////////////////////////////////////////// + /// \brief Fast surface copy to a destination surface + /// + /// \param srcrect Rectangle to be copied, or NullOpt to copy the entire surface + /// \param dst Blit target surface + /// \param srcrect Rectangle that is copied into + /// + /// \throws SDL2pp::Exception + /// + /// \see http://wiki.libsdl.org/SDL_BlitSurface + /// + //////////////////////////////////////////////////////////// + void Blit(const Optional& srcrect, Surface& dst, const Rect& dstrect); + + //////////////////////////////////////////////////////////// + /// \brief Scaled surface copy to a destination surface + /// + /// \param srcrect Rectangle to be copied, or NullOpt to copy the entire surface + /// \param dst Blit target surface + /// \param srcrect Rectangle that is copied into, or NullOpt to copy into entire surface + /// + /// \throws SDL2pp::Exception + /// + /// \see http://wiki.libsdl.org/SDL_BlitScaled + /// + //////////////////////////////////////////////////////////// + void BlitScaled(const Optional& srcrect, Surface& dst, const Optional& dstrect); + + //////////////////////////////////////////////////////////// + /// \brief Lock surface for direct pixel access + /// + /// \return Lock handle used to access pixel data and to control lock lifetime + /// + /// \throws SDL2pp::Exception + /// + /// \see http://wiki.libsdl.org/SDL_LockSurface + /// + //////////////////////////////////////////////////////////// + LockHandle Lock(); + + //////////////////////////////////////////////////////////// + /// \brief Get the clipping rectangle for a surface + /// + /// \return Rect filled in with the clipping rectangle for the surface + /// + /// \see http://wiki.libsdl.org/SDL_GetClipRect + /// + //////////////////////////////////////////////////////////// + Rect GetClipRect() const; + + //////////////////////////////////////////////////////////// + /// \brief Get the color key (transparent pixel) for a surface + /// + /// \return Transparent pixel value + /// + /// \throws SDL2pp::Exception + /// + /// \see http://wiki.libsdl.org/SDL_GetColorKey + /// + //////////////////////////////////////////////////////////// + Uint32 GetColorKey() const; + + //////////////////////////////////////////////////////////// + /// \brief Get the additional alpha value used in blit operations + /// + /// \return Current alpha value + /// + /// \throws SDL2pp::Exception + /// + /// \see http://wiki.libsdl.org/SDL_GetSurfaceAlphaMod + /// + //////////////////////////////////////////////////////////// + Uint8 GetAlphaMod() const; + + //////////////////////////////////////////////////////////// + /// \brief Get blend mode used for blit operations + /// + /// \return Current SDL_BlendMode + /// + /// \throws SDL2pp::Exception + /// + /// \see http://wiki.libsdl.org/SDL_GetSurfaceBlendMode + /// + //////////////////////////////////////////////////////////// + SDL_BlendMode GetBlendMode() const; + + //////////////////////////////////////////////////////////// + /// \brief Get the additional color value multiplied into blit operations + /// + /// \param r Variable to be filled in with the current red color value + /// \param g Variable to be filled in with the current green color value + /// \param b Variable to be filled in with the current blue color value + /// + /// \throws SDL2pp::Exception + /// + /// \see http://wiki.libsdl.org/SDL_GetSurfaceColorMod + /// + //////////////////////////////////////////////////////////// + void GetColorMod(Uint8& r, Uint8& g, Uint8& b) const; + + //////////////////////////////////////////////////////////// + /// \brief Set the clipping rectangle for a surface + /// + /// \param rect SDL22::Rect representing the clipping rectangle, or NullOpt to disable clipping + /// + /// \throws SDL2pp::Exception + /// + /// \see http://wiki.libsdl.org/SDL_SetClipRect + /// + //////////////////////////////////////////////////////////// + void SetClipRect(const Optional& rect = NullOpt); + + //////////////////////////////////////////////////////////// + /// \brief Set the color key (transparent pixel) in a surface + /// + /// \param flag True to enabled color key, false to disable + /// \param key Transparent pixel value + /// + /// \throws SDL2pp::Exception + /// + /// \see http://wiki.libsdl.org/SDL_SetColorKey + /// + //////////////////////////////////////////////////////////// + void SetColorKey(int flag, Uint32 key); + + //////////////////////////////////////////////////////////// + /// \brief Set an additional alpha value used in blit operations + /// + /// \param alpha Alpha value multiplied into blit operations + /// + /// \throws SDL2pp::Exception + /// + /// \see http://wiki.libsdl.org/SDL_SetSurfaceAlphaMod + /// + //////////////////////////////////////////////////////////// + void SetAlphaMod(Uint8 alpha = 255); + + //////////////////////////////////////////////////////////// + /// \brief Set the blend mode used for blit operations + /// + /// \param blendMode SDL_BlendMode to use for blit blending + /// + /// \throws SDL2pp::Exception + /// + /// \see http://wiki.libsdl.org/SDL_SetSurfaceBlendMode + /// + //////////////////////////////////////////////////////////// + void SetBlendMode(SDL_BlendMode blendMode); + + //////////////////////////////////////////////////////////// + /// \brief Set an additional color value multiplied into blit operations + /// + /// \param r Red color value multiplied into blit operations + /// \param g Green color value multiplied into blit operations + /// \param b Blue color value multiplied into blit operations + /// + /// \throws SDL2pp::Exception + /// + /// \see http://wiki.libsdl.org/SDL_SetSurfaceColorMod + /// + //////////////////////////////////////////////////////////// + void SetColorMod(Uint8 r = 255, Uint8 g = 255, Uint8 b = 255); + + //////////////////////////////////////////////////////////// + /// \brief Set the RLE acceleration hint for a surface + /// + /// \param flag 0 to disable, non-zero to enable RLE acceleration + /// + /// \throws SDL2pp::Exception + /// + /// \see http://wiki.libsdl.org/SDL_SetSurfaceRLE + /// + //////////////////////////////////////////////////////////// + void SetRLE(int flag); + + //////////////////////////////////////////////////////////// + /// \brief Perform a fast fill of a rectangle with a specific color + /// + /// \param rect Rectangle to fill, or NullOpt to fill the entire surface + /// \param color Color to fill with + /// + /// \throws SDL2pp::Exception + /// + /// \see http://wiki.libsdl.org/SDL_FillRect + /// + //////////////////////////////////////////////////////////// + void FillRect(const Optional& rect, Uint32 color); + + //////////////////////////////////////////////////////////// + /// \brief Perform a fast fill of a set of rectangles with a specific color + /// + /// \param rects Array rectangles to be filled + /// \param count Number of rectangles in the array + /// \param color Color to fill with + /// + /// \throws SDL2pp::Exception + /// + /// \see http://wiki.libsdl.org/SDL_FillRects + /// + //////////////////////////////////////////////////////////// + void FillRects(const Rect* rects, int count, Uint32 color); +}; + +} + +#endif diff --git a/SDL2pp/SurfaceLock.cc b/SDL2pp/SurfaceLock.cc new file mode 100644 index 0000000..162e80d --- /dev/null +++ b/SDL2pp/SurfaceLock.cc @@ -0,0 +1,79 @@ +/* + 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 { + +Surface::LockHandle::LockHandle() : surface_(nullptr) { +} + +Surface::LockHandle::LockHandle(Surface* surface) : surface_(surface) { + if (SDL_MUSTLOCK(surface_->Get())) { + if (SDL_LockSurface(surface_->Get())) + throw Exception("SDL_LockSurface failed"); + } +} + +Surface::LockHandle::LockHandle(Surface::LockHandle&& other) noexcept : surface_(other.surface_) { + other.surface_ = nullptr; +} + +Surface::LockHandle& Surface::LockHandle::operator=(Surface::LockHandle&& other) noexcept { + if (&other == this) + return *this; + + if (surface_ != nullptr) { + if (SDL_MUSTLOCK(surface_->Get())) + SDL_UnlockSurface(surface_->Get()); + } + + surface_ = other.surface_; + + other.surface_ = nullptr; + + return *this; +} + +Surface::LockHandle::~LockHandle() { + if (surface_ != nullptr) { + if (SDL_MUSTLOCK(surface_->Get())) + SDL_UnlockSurface(surface_->Get()); + } +} + +void* Surface::LockHandle::GetPixels() const { + return surface_->Get()->pixels; +} + +int Surface::LockHandle::GetPitch() const { + return surface_->Get()->pitch; +} + +const SDL_PixelFormat& Surface::LockHandle::GetFormat() const { + return *surface_->Get()->format; +} + +} diff --git a/SDL2pp/Texture.cc b/SDL2pp/Texture.cc index 0750ca3..5308756 100644 --- a/SDL2pp/Texture.cc +++ b/SDL2pp/Texture.cc @@ -33,6 +33,7 @@ #include #include #include +#include #ifdef SDL2PP_WITH_IMAGE # include #endif @@ -56,6 +57,11 @@ Texture::Texture(Renderer& renderer, const std::string& path) { } #endif +Texture::Texture(Renderer& renderer, const Surface& surface) { + if ((texture_ = SDL_CreateTextureFromSurface(renderer.Get(), surface.Get())) == nullptr) + throw Exception("SDL_CreateTextureFromSurface failed"); +} + Texture::~Texture() { if (texture_ != nullptr) SDL_DestroyTexture(texture_); diff --git a/SDL2pp/Texture.hh b/SDL2pp/Texture.hh index e9f58cb..e80fb9c 100644 --- a/SDL2pp/Texture.hh +++ b/SDL2pp/Texture.hh @@ -37,6 +37,7 @@ namespace SDL2pp { class Renderer; class RWops; +class Surface; //////////////////////////////////////////////////////////// /// \brief Image stored in the graphics card memory that @@ -211,6 +212,19 @@ public: Texture(Renderer& renderer, const std::string& filename); #endif + //////////////////////////////////////////////////////////// + /// \brief Create texture from surface + /// + /// \param renderer Rendering context to create texture for + /// \param surface Surface containing pixel data used to fill the texture + /// + /// \throws SDL2pp::Exception + /// + /// \see http://wiki.libsdl.org/SDL_CreateTextureFromSurface + /// + //////////////////////////////////////////////////////////// + Texture(Renderer& renderer, const Surface& surface); + //////////////////////////////////////////////////////////// /// \brief Destructor /// diff --git a/examples/image.cc b/examples/image.cc index a243e1e..c47eeb1 100644 --- a/examples/image.cc +++ b/examples/image.cc @@ -29,6 +29,7 @@ #include #include #include +#include #include using namespace SDL2pp; @@ -39,9 +40,16 @@ int Run() { Window window("libSDL2pp demo: loading", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 480, SDL_WINDOW_RESIZABLE); Renderer render(window, -1, SDL_RENDERER_ACCELERATED); - // Load sprite texture - Texture sprite(render, TESTDATA_DIR "/test.png"); - sprite.SetBlendMode(SDL_BLENDMODE_BLEND); + // Load sprite texture; sprite1 and sprite2 are actually the same + // however first one is loaded directly into texture, and second + // one is loaded through an intermediary surface + Surface surf(TESTDATA_DIR "/test.png"); + + Texture sprite1(render, TESTDATA_DIR "/test.png"); + Texture sprite2(render, surf); + + sprite1.SetBlendMode(SDL_BLENDMODE_BLEND); + sprite2.SetBlendMode(SDL_BLENDMODE_BLEND); render.SetDrawBlendMode(SDL_BLENDMODE_BLEND); @@ -58,9 +66,9 @@ int Run() { // Simple copy float angle = SDL_GetTicks() / 5000.0 * 2.0 * M_PI; - render.Copy(sprite, NullOpt, Rect(320 - 64, 240 - 64, 128, 128), angle / M_PI * 180.0); - render.Copy(sprite, NullOpt, Rect(320 - 32 + sin(angle) * 40, 240 - 32 + cos(angle) * 40, 64, 64)); - render.Copy(sprite, NullOpt, Rect(320 - 32 - sin(angle) * 40, 240 - 32 - cos(angle) * 40, 64, 64)); + render.Copy(sprite1, NullOpt, Rect(320 - 64, 240 - 64, 128, 128), angle / M_PI * 180.0); + render.Copy(sprite1, NullOpt, Rect(320 - 32 + sin(angle) * 40, 240 - 32 + cos(angle) * 40, 64, 64)); + render.Copy(sprite2, NullOpt, Rect(320 - 32 - sin(angle) * 40, 240 - 32 - cos(angle) * 40, 64, 64)); render.Present();