From 8e7156999ee09fec6b21b1a55dc37d3ac326c095 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sat, 29 Jun 2013 01:53:25 +0200 Subject: [PATCH] Allow copying of ImageWrapper, movement of Image and Trade::ImageData. --- src/AbstractImage.cpp | 2 - src/AbstractImage.h | 17 +++----- src/Image.h | 24 +++++++++++ src/ImageWrapper.h | 9 ++-- src/Test/CMakeLists.txt | 1 + src/Test/ImageTest.cpp | 72 ++++++++++++++++++++++++++++++++ src/Trade/ImageData.h | 24 +++++++++++ src/Trade/Test/CMakeLists.txt | 1 + src/Trade/Test/ImageDataTest.cpp | 72 ++++++++++++++++++++++++++++++++ 9 files changed, 205 insertions(+), 17 deletions(-) create mode 100644 src/Test/ImageTest.cpp create mode 100644 src/Trade/Test/ImageDataTest.cpp diff --git a/src/AbstractImage.cpp b/src/AbstractImage.cpp index 0e3af2904..fa5ddcec5 100644 --- a/src/AbstractImage.cpp +++ b/src/AbstractImage.cpp @@ -30,8 +30,6 @@ namespace Magnum { -AbstractImage::~AbstractImage() {} - std::size_t AbstractImage::pixelSize(ImageFormat format, ImageType type) { std::size_t size = 0; switch(type) { diff --git a/src/AbstractImage.h b/src/AbstractImage.h index aef3c71ec..304c3613c 100644 --- a/src/AbstractImage.h +++ b/src/AbstractImage.h @@ -46,11 +46,6 @@ functions operating with images). It also possibly needs to be "stackable" to easily revert the state back. */ class MAGNUM_EXPORT AbstractImage { - AbstractImage(const AbstractImage&) = delete; - AbstractImage(AbstractImage&&) = delete; - AbstractImage& operator=(const AbstractImage&) = delete; - AbstractImage& operator=(AbstractImage&&) = delete; - public: /** * @brief Pixel size (in bytes) @@ -66,16 +61,13 @@ class MAGNUM_EXPORT AbstractImage { * @param format Format of pixel data * @param type Data type of pixel data */ - explicit AbstractImage(ImageFormat format, ImageType type): _format(format), _type(type) {} - - /** @brief Destructor */ - virtual ~AbstractImage() = 0; + constexpr explicit AbstractImage(ImageFormat format, ImageType type): _format(format), _type(type) {} /** @brief Format of pixel data */ - ImageFormat format() const { return _format; } + constexpr ImageFormat format() const { return _format; } /** @brief Data type of pixel data */ - ImageType type() const { return _type; } + constexpr ImageType type() const { return _type; } /** * @brief Pixel size (in bytes) @@ -84,6 +76,9 @@ class MAGNUM_EXPORT AbstractImage { */ std::size_t pixelSize() const { return pixelSize(_format, _type); } + protected: + ~AbstractImage() = default; + #ifdef DOXYGEN_GENERATING_OUTPUT private: #else diff --git a/src/Image.h b/src/Image.h index 54712ae18..6f854adce 100644 --- a/src/Image.h +++ b/src/Image.h @@ -67,6 +67,18 @@ template class Image: public AbstractImage { */ explicit Image(ImageFormat format, ImageType type): AbstractImage(format, type), _data(nullptr) {} + /** @brief Copying is not allowed */ + Image(const Image&& other) = delete; + + /** @brief Move constructor */ + Image(Image&& other) noexcept; + + /** @brief Copying is not allowed */ + Image& operator=(const Image&& other) = delete; + + /** @brief Move assignment */ + Image& operator=(Image&& other) noexcept; + /** @brief Destructor */ ~Image() { delete[] _data; } @@ -103,6 +115,18 @@ typedef Image<2> Image2D; /** @brief Three-dimensional image */ typedef Image<3> Image3D; +template inline Image::Image(Image&& other) noexcept: AbstractImage(std::move(other)), _size(std::move(other._size)), _data(std::move(other._data)) { + other._size = {}; + other._data = nullptr; +} + +template inline Image& Image::operator=(Image&& other) noexcept { + AbstractImage::operator=(std::move(other)); + std::swap(_size, other._size); + std::swap(_data, other._data); + return *this; +} + } #endif diff --git a/src/ImageWrapper.h b/src/ImageWrapper.h index 8acbd16ac..0050a2d63 100644 --- a/src/ImageWrapper.h +++ b/src/ImageWrapper.h @@ -52,6 +52,7 @@ Interchangeable with Image, BufferImage or Trade::ImageData. template class ImageWrapper: public AbstractImage { public: const static UnsignedInt Dimensions = dimensions; /**< @brief %Image dimension count */ + /** * @brief Constructor * @param size %Image size @@ -62,7 +63,7 @@ template class ImageWrapper: public AbstractImage { * Note that the image data are not copied on construction, but they * are deleted on class destruction. */ - explicit ImageWrapper(const typename DimensionTraits::VectorType& size, ImageFormat format, ImageType type, void* data): AbstractImage(format, type), _size(size), _data(reinterpret_cast(data)) {} + constexpr explicit ImageWrapper(const typename DimensionTraits::VectorType& size, ImageFormat format, ImageType type, void* data): AbstractImage(format, type), _size(size), _data(reinterpret_cast(data)) {} /** * @brief Constructor @@ -73,14 +74,14 @@ template class ImageWrapper: public AbstractImage { * Data pointer is set to zero, call setData() to fill the image with * data. */ - explicit ImageWrapper(const typename DimensionTraits::VectorType& size, ImageFormat format, ImageType type): AbstractImage(format, type), _size(size), _data(nullptr) {} + constexpr explicit ImageWrapper(const typename DimensionTraits::VectorType& size, ImageFormat format, ImageType type): AbstractImage(format, type), _size(size), _data(nullptr) {} /** @brief %Image size */ - typename DimensionTraits::VectorType size() const { return _size; } + constexpr typename DimensionTraits::VectorType size() const { return _size; } /** @brief Pointer to raw data */ unsigned char* data() { return _data; } - const unsigned char* data() const { return _data; } /**< @overload */ + constexpr const unsigned char* data() const { return _data; } /**< @overload */ /** * @brief Set image data diff --git a/src/Test/CMakeLists.txt b/src/Test/CMakeLists.txt index e9138989f..3998a58ee 100644 --- a/src/Test/CMakeLists.txt +++ b/src/Test/CMakeLists.txt @@ -28,6 +28,7 @@ corrade_add_test(ArrayTest ArrayTest.cpp) corrade_add_test(ColorTest ColorTest.cpp LIBRARIES MagnumMathTestLib) corrade_add_test(DefaultFramebufferTest DefaultFramebufferTest.cpp LIBRARIES Magnum) corrade_add_test(FramebufferTest FramebufferTest.cpp LIBRARIES Magnum) +corrade_add_test(ImageTest ImageTest.cpp LIBRARIES Magnum) corrade_add_test(MeshTest MeshTest.cpp LIBRARIES Magnum) corrade_add_test(RendererTest RendererTest.cpp LIBRARIES Magnum) corrade_add_test(ResourceManagerTest ResourceManagerTest.cpp LIBRARIES MagnumTestLib) diff --git a/src/Test/ImageTest.cpp b/src/Test/ImageTest.cpp new file mode 100644 index 000000000..70097e1f3 --- /dev/null +++ b/src/Test/ImageTest.cpp @@ -0,0 +1,72 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013 Vladimír Vondruš + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +#include + +#include "Image.h" +#include "ImageFormat.h" + +namespace Magnum { namespace Test { + +class ImageTest: public TestSuite::Tester { + public: + explicit ImageTest(); + + void moveConstructor(); + void moveAssignment(); +}; + +ImageTest::ImageTest() { + addTests({&ImageTest::moveConstructor, + &ImageTest::moveAssignment}); +} + +void ImageTest::moveConstructor() { + unsigned char* data = new unsigned char[3]; + Image2D a({1, 3}, ImageFormat::Red, ImageType::UnsignedByte, data); + + Image2D b(std::move(a)); + CORRADE_VERIFY(!a.data()); + CORRADE_COMPARE(b.format(), ImageFormat::Red); + CORRADE_COMPARE(b.type(), ImageType::UnsignedByte); + CORRADE_COMPARE(b.size(), Vector2i(1, 3)); + CORRADE_VERIFY(b.data() == data); +} + +void ImageTest::moveAssignment() { + unsigned char* data = new unsigned char[3]; + Image2D a({1, 3}, ImageFormat::Red, ImageType::UnsignedByte, data); + + Image2D b(ImageFormat::Red, ImageType::UnsignedByte); + b = std::move(a); + CORRADE_VERIFY(!a.data()); + CORRADE_COMPARE(b.format(), ImageFormat::Red); + CORRADE_COMPARE(b.type(), ImageType::UnsignedByte); + CORRADE_COMPARE(b.size(), Vector2i(1, 3)); + CORRADE_VERIFY(b.data() == data); +} + +}} + +CORRADE_TEST_MAIN(Magnum::Test::ImageTest) diff --git a/src/Trade/ImageData.h b/src/Trade/ImageData.h index ab134a96a..7e56c1359 100644 --- a/src/Trade/ImageData.h +++ b/src/Trade/ImageData.h @@ -57,6 +57,18 @@ template class ImageData: public AbstractImage { */ explicit ImageData(const typename DimensionTraits::VectorType& size, ImageFormat format, ImageType type, void* data): AbstractImage(format, type), _size(size), _data(reinterpret_cast(data)) {} + /** @brief Copying is not allowed */ + ImageData(const ImageData&& other) = delete; + + /** @brief Move constructor */ + ImageData(ImageData&& other) noexcept; + + /** @brief Copying is not allowed */ + ImageData& operator=(const ImageData&& other) = delete; + + /** @brief Move assignment */ + ImageData& operator=(ImageData&& other) noexcept; + /** @brief Destructor */ ~ImageData() { delete[] _data; } @@ -81,6 +93,18 @@ typedef ImageData<2> ImageData2D; /** @brief Three-dimensional image */ typedef ImageData<3> ImageData3D; +template inline ImageData::ImageData(ImageData&& other) noexcept: AbstractImage(std::move(other)), _size(std::move(other._size)), _data(std::move(other._data)) { + other._size = {}; + other._data = nullptr; +} + +template inline ImageData& ImageData::operator=(ImageData&& other) noexcept { + AbstractImage::operator=(std::move(other)); + std::swap(_size, other._size); + std::swap(_data, other._data); + return *this; +} + }} #endif diff --git a/src/Trade/Test/CMakeLists.txt b/src/Trade/Test/CMakeLists.txt index a3c163349..beb1c2ccf 100644 --- a/src/Trade/Test/CMakeLists.txt +++ b/src/Trade/Test/CMakeLists.txt @@ -29,5 +29,6 @@ include_directories(${CMAKE_CURRENT_BINARY_DIR}) corrade_add_test(TradeAbstractImageConverterTest AbstractImageConverterTest.cpp LIBRARIES Magnum) corrade_add_test(TradeAbstractImporterTest AbstractImporterTest.cpp LIBRARIES Magnum) +corrade_add_test(TradeImageDataTest ImageDataTest.cpp LIBRARIES Magnum) corrade_add_test(TradeObjectData2DTest ObjectData2DTest.cpp LIBRARIES Magnum) corrade_add_test(TradeObjectData3DTest ObjectData3DTest.cpp LIBRARIES Magnum) diff --git a/src/Trade/Test/ImageDataTest.cpp b/src/Trade/Test/ImageDataTest.cpp new file mode 100644 index 000000000..6a5c300dc --- /dev/null +++ b/src/Trade/Test/ImageDataTest.cpp @@ -0,0 +1,72 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013 Vladimír Vondruš + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +#include + +#include "ImageFormat.h" +#include "Trade/ImageData.h" + +namespace Magnum { namespace Trade { namespace Test { + +class ImageDataTest: public TestSuite::Tester { + public: + explicit ImageDataTest(); + + void moveConstructor(); + void moveAssignment(); +}; + +ImageDataTest::ImageDataTest() { + addTests({&ImageDataTest::moveConstructor, + &ImageDataTest::moveAssignment}); +} + +void ImageDataTest::moveConstructor() { + unsigned char* data = new unsigned char[3]; + Trade::ImageData2D a({1, 3}, ImageFormat::Red, ImageType::UnsignedByte, data); + + Trade::ImageData2D b(std::move(a)); + CORRADE_VERIFY(!a.data()); + CORRADE_COMPARE(b.format(), ImageFormat::Red); + CORRADE_COMPARE(b.type(), ImageType::UnsignedByte); + CORRADE_COMPARE(b.size(), Vector2i(1, 3)); + CORRADE_VERIFY(b.data() == data); +} + +void ImageDataTest::moveAssignment() { + unsigned char* data = new unsigned char[3]; + Trade::ImageData2D a({1, 3}, ImageFormat::Red, ImageType::UnsignedByte, data); + + Trade::ImageData2D b({}, ImageFormat::Red, ImageType::UnsignedByte, nullptr); + b = std::move(a); + CORRADE_VERIFY(!a.data()); + CORRADE_COMPARE(b.format(), ImageFormat::Red); + CORRADE_COMPARE(b.type(), ImageType::UnsignedByte); + CORRADE_COMPARE(b.size(), Vector2i(1, 3)); + CORRADE_VERIFY(b.data() == data); +} + +}}} + +CORRADE_TEST_MAIN(Magnum::Trade::Test::ImageDataTest)