diff --git a/src/AbstractTexture.h b/src/AbstractTexture.h index 97f6fbb3f..c7e2ef512 100644 --- a/src/AbstractTexture.h +++ b/src/AbstractTexture.h @@ -20,6 +20,7 @@ */ #include "Magnum.h" +#include "Color.h" namespace Magnum { @@ -611,7 +612,7 @@ class MAGNUM_EXPORT AbstractTexture { * to `ClampToBorder`. * @requires_gl */ - inline void setBorderColor(const Vector4& color) { + inline void setBorderColor(const Color4& color) { bind(); glTexParameterfv(_target, GL_TEXTURE_BORDER_COLOR, color.data()); } diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 2f6fec80f..cd2fe4927 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -40,6 +40,7 @@ set(Magnum_HEADERS BufferedTexture.h Buffer.h Camera.h + Color.h CubeMapTextureArray.h CubeMapTexture.h Framebuffer.h diff --git a/src/Color.h b/src/Color.h new file mode 100644 index 000000000..7dd384a1f --- /dev/null +++ b/src/Color.h @@ -0,0 +1,409 @@ +#ifndef Magnum_Color_h +#define Magnum_Color_h +/* + Copyright © 2010, 2011, 2012 Vladimír Vondruš + + This file is part of Magnum. + + Magnum is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License version 3 + only, as published by the Free Software Foundation. + + Magnum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License version 3 for more details. +*/ + +/** @file + * @brief Class Magnum::Color3, Magnum::Color4 + */ + +#include + +#include "Math/MathTypeTraits.h" +#include "Math/Math.h" +#include "Math/Vector4.h" + +namespace Magnum { + +template class Color3; + +#ifndef DOXYGEN_GENERATING_OUTPUT +namespace Implementation { + +/* Convert color from HSV */ +template inline typename std::enable_if::value, Color3>::type fromHSV(typename Color3::HSV hsv) { + T hue, saturation, value; + std::tie(hue, saturation, value) = hsv; + + /* Remove repeats */ + hue -= int(hue/T(360))*T(360); + if(hue < T(0)) hue += T(360); + + int h = int(hue/T(60)) % 6; + T f = hue/T(60) - h; + + T p = value * (T(1) - saturation); + T q = value * (T(1) - f*saturation); + T t = value * (T(1) - (T(1) - f)*saturation); + + switch(h) { + case 0: return {value, t, p}; + case 1: return {q, value, p}; + case 2: return {p, value, t}; + case 3: return {p, q, value}; + case 4: return {t, p, value}; + case 5: return {value, p, q}; + default: + CORRADE_ASSERT(false, "It shouldn't get here.", {}); + } +} +template inline typename std::enable_if::value, Color3>::type fromHSV(typename Color3::HSV hsv) { + return Color3::fromNormalized(fromHSV::FloatingPointType>(hsv)); +} + +/* Internal hue computing function */ +template T hue(const Color3& color, T max, T delta) { + T deltaInv60 = T(60)/delta; + + T hue(0); + if(delta != T(0)) { + if(max == color.r()) + hue = (color.g()-color.b())*deltaInv60 + (color.g() < color.b() ? T(360) : T(0)); + else if(max == color.g()) + hue = (color.b()-color.r())*deltaInv60 + T(120); + else /* max == color.b() */ + hue = (color.r()-color.g())*deltaInv60 + T(240); + } + + return hue; +} + +/* Hue, saturation, value for floating-point types */ +template inline T hue(typename std::enable_if::value, const Color3&>::type color) { + T max = color.max(); + T delta = max - color.min(); + return hue(color, max, delta); +} +template inline T saturation(typename std::enable_if::value, const Color3&>::type color) { + T max = color.max(); + T delta = max - color.min(); + return max != T(0) ? delta/max : T(0); +} +template inline T value(typename std::enable_if::value, const Color3&>::type color) { + return color.max(); +} + +/* Hue, saturation, value for integral types */ +template inline typename Color3::FloatingPointType hue(typename std::enable_if::value, const Color3&>::type color) { + return hue::FloatingPointType>(Color3::FloatingPointType>::fromDenormalized(color)); +} +template inline typename Color3::FloatingPointType saturation(typename std::enable_if::value, const Color3&>::type& color) { + return saturation::FloatingPointType>(Color3::FloatingPointType>::fromDenormalized(color)); +} +template inline typename Color3::FloatingPointType value(typename std::enable_if::value, const Color3&>::type color) { + return Math::normalize::FloatingPointType>(color.max()); +} + +/* Convert color to HSV */ +template inline typename Color3::HSV toHSV(typename std::enable_if::value, const Color3&>::type color) { + T max = color.max(); + T delta = max - color.min(); + + return typename Color3::HSV(hue::FloatingPointType>(color, max, delta), max != T(0) ? delta/max : T(0), max); +} +template inline typename Color3::HSV toHSV(typename std::enable_if::value, const Color3&>::type color) { + return toHSV::FloatingPointType>(Color3::FloatingPointType>::fromDenormalized(color)); +} + +/* Default alpha value */ +template inline constexpr typename std::enable_if::value, T>::type defaultAlpha() { + return T(1); +} +template inline constexpr typename std::enable_if::value, T>::type defaultAlpha() { + return std::numeric_limits::max(); +} + +} +#endif + +/** +@brief Three-component (RGB) color + +The class can store both floating-point (normalized) and integral +(denormalized) representation of color. You can convert between these two +representations using fromNormalized() and fromDenormalized(). + +Conversion from and to HSV is done always using floating-point types, so hue +is always in range in range @f$ [0.0, 360.0] @f$, saturation and value in +range @f$ [0.0, 1.0] @f$. + +@see Color4 +*/ +template class Color3: public Math::Vector3 { + public: + /** @brief Corresponding floating-point type for HSV computation */ + typedef typename Math::MathTypeTraits::FloatingPointType FloatingPointType; + + /** + * @brief Type for storing HSV values + * + * Hue in range @f$ [0.0, 360.0] @f$, saturation and value in + * range @f$ [0.0, 1.0] @f$. + */ + typedef std::tuple HSV; + + /** + * @brief Create integral color from floating-point color + * + * E.g. `{0.294118, 0.45098, 0.878431}` is converted to + * `{75, 115, 224}`, if resulting type is `unsigned char`. + * + * @note This function is enabled only if source type is floating-point + * and destination type is integral. + */ + template inline constexpr static typename std::enable_if::value && std::is_floating_point::value, Color3>::type fromNormalized(const Color3& color) { + return Color3(Math::denormalize(color.r()), + Math::denormalize(color.g()), + Math::denormalize(color.b())); + } + + /** + * @brief Create floating-point color from integral color + * + * E.g. `{75, 115, 224}` is converted to + * `{0.294118, 0.45098, 0.878431}`, if source type is `unsigned char`. + * + * @note This function is enabled only if source type is integral + * and destination type is floating-point. + */ + template inline constexpr static typename std::enable_if::value && std::is_integral::value, Color3>::type fromDenormalized(const Color3& color) { + return Color3(Math::normalize(color.r()), + Math::normalize(color.g()), + Math::normalize(color.b())); + } + + /** + * @brief Create RGB color from HSV representation + * @param hsv Hue, saturation and value + * + * Hue can overflow the range @f$ [0.0, 360.0] @f$. + */ + inline constexpr static Color3 fromHSV(HSV hsv) { + return Implementation::fromHSV(hsv); + } + /** @overload */ + inline constexpr static Color3 fromHSV(FloatingPointType hue, FloatingPointType saturation, FloatingPointType value) { + return fromHSV(std::make_tuple(hue, saturation, value)); + } + + /** + * @brief Default constructor + * + * All components are set to zero. + */ + inline constexpr Color3() {} + + /** + * @brief Gray constructor + * @param rgb RGB value + */ + inline constexpr explicit Color3(T rgb): Math::Vector3(rgb) {} + + /** @copydoc Math::Vector::Vector(const Vector&) */ + inline constexpr Color3(const Math::Vector<3, T>& other): Math::Vector3(other) {} + + /** + * @brief Constructor + * @param r R value + * @param g G value + * @param b B value + */ + inline constexpr Color3(T r, T g, T b): Math::Vector3(r, g, b) {} + + inline constexpr T r() const { return Math::Vector3::x(); } /**< @brief R component */ + inline constexpr T g() const { return Math::Vector3::y(); } /**< @brief G component */ + inline constexpr T b() const { return Math::Vector3::z(); } /**< @brief B component */ + + inline void setR(T value) { Math::Vector3::setX(value); } /**< @brief Set R component */ + inline void setG(T value) { Math::Vector3::setY(value); } /**< @brief Set G component */ + inline void setB(T value) { Math::Vector3::setZ(value); } /**< @brief Set B component */ + + /** + * @brief Convert to HSV + * + * Example usage: + * @code + * T hue, saturation, value; + * std::tie(hue, saturation, value) = color.toHSV(); + * @endcode + * + * @see hue(), saturation(), value(), fromHSV() + */ + inline constexpr HSV toHSV() const { + return Implementation::toHSV(*this); + } + + /** + * @brief Hue + * @return Hue in range @f$ [0.0, 360.0] @f$. + * + * @see saturation(), value(), toHSV(), fromHSV() + */ + inline constexpr FloatingPointType hue() const { + return Implementation::hue(*this); + } + + /** + * @brief Saturation + * @return Saturation in range @f$ [0.0, 1.0] @f$. + * + * @see hue(), value(), toHSV(), fromHSV() + */ + inline constexpr FloatingPointType saturation() const { + return Implementation::saturation(*this); + } + + /** + * @brief Value + * @return Value in range @f$ [0.0, 1.0] @f$. + * + * @see hue(), saturation(), toHSV(), fromHSV() + */ + inline constexpr FloatingPointType value() const { + return Implementation::value(*this); + } +}; + +/** +@brief Four-component (RGBA) color + +See Color3 for more information. +*/ +template class Color4: public Math::Vector4 { + public: + /** @copydoc Color3::FloatingPointType */ + typedef typename Color3::FloatingPointType FloatingPointType; + + /** @copydoc Color3::HSV */ + typedef typename Color3::HSV HSV; + + /** @copydoc Color3::fromNormalized() */ + template inline constexpr static typename std::enable_if::value && std::is_floating_point::value, Color4>::type fromNormalized(const Color4& color) { + return Color4(Math::denormalize(color.r()), + Math::denormalize(color.g()), + Math::denormalize(color.b()), + Math::denormalize(color.a())); + } + + /** @copydoc Color3::fromDenormalized() */ + template inline constexpr static typename std::enable_if::value && std::is_integral::value, Color4>::type fromDenormalized(const Color4& color) { + return Color4(Math::normalize(color.r()), + Math::normalize(color.g()), + Math::normalize(color.b()), + Math::normalize(color.a())); + } + + /** + * @copydoc Color3::fromHSV() + * @param a Alpha value, defaults to 1.0 for floating-point types + * and maximum positive value for integral types. + */ + inline constexpr static Color4 fromHSV(HSV hsv, T a = Implementation::defaultAlpha()) { + return Color4(Implementation::fromHSV(hsv), a); + } + /** @overload */ + inline constexpr static Color4 fromHSV(FloatingPointType hue, FloatingPointType saturation, FloatingPointType value, T alpha) { + return fromHSV(std::make_tuple(hue, saturation, value), alpha); + } + + /** + * @brief Default constructor + * + * RGB components are set to zero, A component is set to 1.0 for + * floating-point types and maximum positive value for integral types. + */ + inline constexpr Color4(): Math::Vector4(T(0), T(0), T(0), Implementation::defaultAlpha()) {} + + /** + * @copydoc Color3::Color3(T) + * @param alpha Alpha value, defaults to 1.0 for floating-point types + * and maximum positive value for integral types. + */ + inline constexpr explicit Color4(T rgb, T alpha = Implementation::defaultAlpha()): Math::Vector4(rgb, rgb, rgb, alpha) {} + + /** @copydoc Math::Vector::Vector(const Vector&) */ + inline constexpr Color4(const Math::Vector<4, T>& other): Math::Vector4(other) {} + + /** + * @brief Constructor + * @param r R value + * @param g G value + * @param b B value + * @param a A value, defaults to 1.0 for floating-point types and + * maximum positive value for integral types. + */ + inline constexpr Color4(T r, T g, T b, T a = Implementation::defaultAlpha()): Math::Vector4(r, g, b, a) {} + + /** + * @brief Constructor + * @param rgb Three-component color + * @param a A value + */ + /* Not marked as explicit, because conversion from Color3 to Color4 + is fairly common, nearly always with A set to 1 */ + inline constexpr Color4(const Math::Vector<3, T>& rgb, T a = Implementation::defaultAlpha()): Math::Vector4(rgb[0], rgb[1], rgb[2], a) {} + + inline constexpr T r() const { return Math::Vector4::x(); } /**< @brief R component */ + inline constexpr T g() const { return Math::Vector4::y(); } /**< @brief G component */ + inline constexpr T b() const { return Math::Vector4::z(); } /**< @brief B component */ + inline constexpr T a() const { return Math::Vector4::w(); } /**< @brief A component */ + + inline void setR(T value) { Math::Vector4::setX(value); } /**< @brief Set R component */ + inline void setG(T value) { Math::Vector4::setY(value); } /**< @brief Set G component */ + inline void setB(T value) { Math::Vector4::setZ(value); } /**< @brief Set B component */ + inline void setA(T value) { Math::Vector4::setW(value); } /**< @brief Set A component */ + + /** + * @brief RGB part of the vector + * @return First three components of the vector + * + * @see swizzle() + */ + inline constexpr Color3 rgb() const { return Math::Vector4::xyz(); } + + /** @copydoc Color3::toHSV() */ + inline constexpr HSV toHSV() const { + return Implementation::toHSV(rgb()); + } + + /** @copydoc Color3::hue() */ + inline constexpr FloatingPointType hue() const { + return Implementation::hue(rgb()); + } + + /** @copydoc Color3::saturation() */ + inline constexpr FloatingPointType saturation() const { + return Implementation::saturation(rgb()); + } + + /** @copydoc Color3::value() */ + inline constexpr FloatingPointType value() const { + return Implementation::value(rgb()); + } +}; + +/** @debugoperator{Color3} */ +template Corrade::Utility::Debug operator<<(Corrade::Utility::Debug debug, const Magnum::Color3& value) { + return debug << static_cast&>(value); +} + +/** @debugoperator{Color4} */ +template Corrade::Utility::Debug operator<<(Corrade::Utility::Debug debug, const Magnum::Color4& value) { + return debug << static_cast&>(value); +} + +} + +#endif diff --git a/src/Framebuffer.h b/src/Framebuffer.h index f88a47637..27ee0cb85 100644 --- a/src/Framebuffer.h +++ b/src/Framebuffer.h @@ -23,6 +23,7 @@ #include "BufferedImage.h" #include "CubeMapTexture.h" +#include "Color.h" #include "Image.h" #include "Renderbuffer.h" @@ -192,7 +193,7 @@ class MAGNUM_EXPORT Framebuffer { * * Initial value is `{0.0f, 0.0f, 0.0f, 1.0f}`. */ - inline static void setClearColor(const Vector4& color) { + inline static void setClearColor(const Color4& color) { glClearColor(color.r(), color.g(), color.b(), color.a()); } diff --git a/src/Math/Vector3.h b/src/Math/Vector3.h index 2d43ef63b..a4d24fc56 100644 --- a/src/Math/Vector3.h +++ b/src/Math/Vector3.h @@ -57,16 +57,16 @@ template class Vector3: public Vector<3, T> { /** * @brief Constructor - * @param x X / R value - * @param y Y / G value - * @param z Z / B value + * @param x X value + * @param y Y value + * @param z Z value */ inline constexpr Vector3(T x, T y, T z): Vector<3, T>(x, y, z) {} /** * @brief Constructor * @param other Two component vector - * @param z Z / B value + * @param z Z value */ inline constexpr Vector3(const Vector<2, T>& other, T z): Vector<3, T>(other[0], other[1], z) {} @@ -86,14 +86,6 @@ template class Vector3: public Vector<3, T> { */ inline constexpr Vector2 xy() const { return Vector2::from(Vector<3, T>::data()); } - inline constexpr T r() const { return x(); } /**< @brief R component */ - inline constexpr T g() const { return y(); } /**< @brief G component */ - inline constexpr T b() const { return z(); } /**< @brief B component */ - - inline void setR(T value) { setX(value); } /**< @brief Set R component */ - inline void setG(T value) { setY(value); } /**< @brief Set G component */ - inline void setB(T value) { setZ(value); } /**< @brief Set B component */ - MAGNUM_VECTOR_SUBCLASS_IMPLEMENTATION(Vector3, 3) }; diff --git a/src/Math/Vector4.h b/src/Math/Vector4.h index 430b80de0..490f2dcea 100644 --- a/src/Math/Vector4.h +++ b/src/Math/Vector4.h @@ -29,7 +29,7 @@ template class Vector4: public Vector<4, T> { /** * @copydoc Vector::Vector * - * W / A component is set to one. + * W component is set to one. */ inline constexpr Vector4(): Vector<4, T>(T(0), T(0), T(0), T(1)) {} @@ -41,17 +41,17 @@ template class Vector4: public Vector<4, T> { /** * @brief Constructor - * @param x X / R value - * @param y Y / G value - * @param z Z / B value - * @param w W / A value + * @param x X value + * @param y Y value + * @param z Z value + * @param w W value */ inline constexpr Vector4(T x, T y, T z, T w = T(1)): Vector<4, T>(x, y, z, w) {} /** * @brief Constructor * @param other Three component vector - * @param w W / A value + * @param w W value */ /* Not marked as explicit, because conversion from Vector3 to Vector4 is fairly common, nearly always with W set to 1 */ @@ -83,24 +83,6 @@ template class Vector4: public Vector<4, T> { */ inline constexpr Vector2 xy() const { return Vector2::from(Vector<4, T>::data()); } - inline constexpr T r() const { return x(); } /**< @brief R component */ - inline constexpr T g() const { return y(); } /**< @brief G component */ - inline constexpr T b() const { return z(); } /**< @brief B component */ - inline constexpr T a() const { return w(); } /**< @brief A component */ - - inline void setR(T value) { setX(value); } /**< @brief Set R component */ - inline void setG(T value) { setY(value); } /**< @brief Set G component */ - inline void setB(T value) { setZ(value); } /**< @brief Set B component */ - inline void setA(T value) { setW(value); } /**< @brief Set A component */ - - /** - * @brief RGB part of the vector - * @return First three components of the vector - * - * @see swizzle() - */ - inline constexpr Vector3 rgb() const { return xyz(); } - MAGNUM_VECTOR_SUBCLASS_IMPLEMENTATION(Vector4, 4) }; diff --git a/src/Test/CMakeLists.txt b/src/Test/CMakeLists.txt index 61f80a3a6..6c20f9a69 100644 --- a/src/Test/CMakeLists.txt +++ b/src/Test/CMakeLists.txt @@ -1,3 +1,5 @@ corrade_add_test2(ObjectTest ObjectTest.cpp LIBRARIES MagnumTestLib) corrade_add_test2(CameraTest CameraTest.cpp LIBRARIES Magnum) corrade_add_test2(SceneTest SceneTest.cpp LIBRARIES Magnum) + +corrade_add_test2(ColorTest ColorTest.cpp) diff --git a/src/Test/ColorTest.cpp b/src/Test/ColorTest.cpp new file mode 100644 index 000000000..a500ffee4 --- /dev/null +++ b/src/Test/ColorTest.cpp @@ -0,0 +1,121 @@ +/* + Copyright © 2010, 2011, 2012 Vladimír Vondruš + + This file is part of Magnum. + + Magnum is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License version 3 + only, as published by the Free Software Foundation. + + Magnum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License version 3 for more details. +*/ + +#include "ColorTest.h" + +#include "Color.h" + +using namespace std; + +CORRADE_TEST_MAIN(Magnum::Test::ColorTest) + +namespace Magnum { namespace Test { + +typedef Magnum::Color3 Color3; +typedef Magnum::Color4 Color4; +typedef Magnum::Color3 Color3f; + +ColorTest::ColorTest() { + addTests(&ColorTest::fromDenormalized, + &ColorTest::fromNormalized, + + &ColorTest::fromHue, + &ColorTest::fromSaturation, + &ColorTest::fromValue, + + &ColorTest::hue, + &ColorTest::saturation, + &ColorTest::value, + + &ColorTest::hsv, + &ColorTest::hsvOverflow, + &ColorTest::hsvAlpha); +} + +void ColorTest::fromDenormalized() { + CORRADE_COMPARE(Color3f::fromDenormalized(Color3(75, 115, 224)), Color3f(0.294118, 0.45098, 0.878431)); +} + +void ColorTest::fromNormalized() { + CORRADE_COMPARE(Color3::fromNormalized(Color3f(0.294118, 0.45098, 0.878431)), Color3(75, 115, 224)); +} + +void ColorTest::fromHue() { + CORRADE_COMPARE(Color3::fromHSV(27.0f, 1.0f, 1.0f), Color3(255, 115, 0)); + CORRADE_COMPARE(Color3::fromHSV(86.0f, 1.0f, 1.0f), Color3(145, 255, 0)); + CORRADE_COMPARE(Color3::fromHSV(134.0f, 1.0f, 1.0f), Color3(0, 255, 60)); + CORRADE_COMPARE(Color3::fromHSV(191.0f, 1.0f, 1.0f), Color3(0, 208, 255)); + CORRADE_COMPARE(Color3::fromHSV(269.0f, 1.0f, 1.0f), Color3(123, 0, 255)); + CORRADE_COMPARE(Color3::fromHSV(317.0f, 1.0f, 1.0f), Color3(255, 0, 183)); +} + +void ColorTest::hue() { + CORRADE_COMPARE(Color3(255, 115, 0).hue(), 27.058824f); + CORRADE_COMPARE(Color3(145, 255, 0).hue(), 85.882353f); + CORRADE_COMPARE(Color3(0, 255, 60).hue(), 134.11765f); + CORRADE_COMPARE(Color3(0, 208, 255).hue(), 191.05882f); + CORRADE_COMPARE(Color3(123, 0, 255).hue(), 268.94117f); + CORRADE_COMPARE(Color3(255, 0, 183).hue(), 316.94117f); +} + +void ColorTest::fromSaturation() { + CORRADE_COMPARE(Color3::fromHSV(0.0f, 0.702f, 1.0f), Color3(255, 76, 76)); +} + +void ColorTest::saturation() { + CORRADE_COMPARE(Color3(255, 76, 76).saturation(), 0.701961f); + CORRADE_COMPARE(Color3().saturation(), 0.0f); +} + +void ColorTest::fromValue() { + CORRADE_COMPARE(Color3::fromHSV(0.0f, 1.0f, 0.522f), Color3(133, 0, 0)); +} + +void ColorTest::value() { + CORRADE_COMPARE(Color3(133, 0, 0).value(), 0.521569f); +} + +void ColorTest::hsv() { + CORRADE_COMPARE(Color3::fromHSV(230.0f, 0.749f, 0.427f), Color3(27, 41, 109)); + + float hue, saturation, value; + tie(hue, saturation, value) = Color3(27, 41, 109).toHSV(); + CORRADE_COMPARE(hue, 229.756106f); + CORRADE_COMPARE(saturation, 0.752294f); + CORRADE_COMPARE(value, 0.427451f); +} + +void ColorTest::hsvOverflow() { + CORRADE_COMPARE(Color3::fromHSV(27.0f-360.0f, 1.0f, 1.0f), Color3(255, 115, 0)); + CORRADE_COMPARE(Color3::fromHSV(86.0f-360.0f, 1.0f, 1.0f), Color3(145, 255, 0)); + CORRADE_COMPARE(Color3::fromHSV(134.0f-360.0f, 1.0f, 1.0f), Color3(0, 255, 60)); + CORRADE_COMPARE(Color3::fromHSV(191.0f-360.0f, 1.0f, 1.0f), Color3(0, 208, 255)); + CORRADE_COMPARE(Color3::fromHSV(269.0f-360.0f, 1.0f, 1.0f), Color3(123, 0, 255)); + CORRADE_COMPARE(Color3::fromHSV(317.0f-360.0f, 1.0f, 1.0f), Color3(255, 0, 183)); + + CORRADE_COMPARE(Color3::fromHSV(360.0f+27.0f, 1.0f, 1.0f), Color3(255, 115, 0)); + CORRADE_COMPARE(Color3::fromHSV(360.0f+86.0f, 1.0f, 1.0f), Color3(145, 255, 0)); + CORRADE_COMPARE(Color3::fromHSV(360.0f+134.0f, 1.0f, 1.0f), Color3(0, 255, 60)); + CORRADE_COMPARE(Color3::fromHSV(360.0f+191.0f, 1.0f, 1.0f), Color3(0, 208, 255)); + CORRADE_COMPARE(Color3::fromHSV(360.0f+269.0f, 1.0f, 1.0f), Color3(123, 0, 255)); + CORRADE_COMPARE(Color3::fromHSV(360.0f+317.0f, 1.0f, 1.0f), Color3(255, 0, 183)); +} + +void ColorTest::hsvAlpha() { + CORRADE_COMPARE(Color4::fromHSV(make_tuple(230.0f, 0.749f, 0.427f), 23), Color4(27, 41, 109, 23)); + CORRADE_COMPARE(Color4::fromHSV(230.0f, 0.749f, 0.427f, 23), Color4(27, 41, 109, 23)); +} + +}} diff --git a/src/Test/ColorTest.h b/src/Test/ColorTest.h new file mode 100644 index 000000000..068e36da6 --- /dev/null +++ b/src/Test/ColorTest.h @@ -0,0 +1,44 @@ +#ifndef Magnum_Test_ColorTest_h +#define Magnum_Test_ColorTest_h +/* + Copyright © 2010, 2011, 2012 Vladimír Vondruš + + This file is part of Magnum. + + Magnum is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License version 3 + only, as published by the Free Software Foundation. + + Magnum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License version 3 for more details. +*/ + +#include + +namespace Magnum { namespace Test { + +class ColorTest: public Corrade::TestSuite::Tester { + public: + ColorTest(); + + void fromDenormalized(); + void fromNormalized(); + + void fromHue(); + void fromSaturation(); + void fromValue(); + + void hue(); + void saturation(); + void value(); + + void hsv(); + void hsvOverflow(); + void hsvAlpha(); +}; + +}} + +#endif