diff --git a/doc/changelog.dox b/doc/changelog.dox index 2df198489..c1bac466b 100644 --- a/doc/changelog.dox +++ b/doc/changelog.dox @@ -294,6 +294,10 @@ See also: @subsection changelog-latest-deprecated Deprecated APIs +- @cpp Math::Color3::Hsv @ce and @cpp Math::Color4::Hsv @ce tuple typedefs + are deprecated in favor of tuple-less @ref Math::ColorHsv, working + correctly with the usual @ref Math::NoInit / @ref Math::ZeroInit tags while + being faster to compile - @cpp Trade::ImporterFileCallbackPolicy @ce is deprecated as it was moved to @ref InputFileCallbackPolicy in the root namespace to be shared with APIs outside of the @ref Trade namespace diff --git a/doc/generated/shaders.cpp b/doc/generated/shaders.cpp index d0437dffd..f13f7614e 100644 --- a/doc/generated/shaders.cpp +++ b/doc/generated/shaders.cpp @@ -194,7 +194,7 @@ std::string ShaderVisualizer::vertexColor() { std::vector colors; colors.reserve(sphere.positions(0).size()); for(Vector3 position: sphere.positions(0)) - colors.push_back(Color3::fromHsv(Math::lerp(240.0_degf, 420.0_degf, Math::max(1.0f - (position - target).length(), 0.0f)), 0.85f, 0.666f)); + colors.push_back(Color3::fromHsv({Math::lerp(240.0_degf, 420.0_degf, Math::max(1.0f - (position - target).length(), 0.0f)), 0.85f, 0.666f})); GL::Buffer vertices, indices; vertices.setData(MeshTools::interleave(sphere.positions(0), colors), GL::BufferUsage::StaticDraw); diff --git a/doc/snippets/MagnumDebugTools-gl.cpp b/doc/snippets/MagnumDebugTools-gl.cpp index 83d2160fe..3be3cd82c 100644 --- a/doc/snippets/MagnumDebugTools-gl.cpp +++ b/doc/snippets/MagnumDebugTools-gl.cpp @@ -71,7 +71,7 @@ SceneGraph::DrawableGroup3D debugDrawables; DebugTools::ResourceManager::instance().set("my", DebugTools::ForceRendererOptions{} .setSize(5.0f) - .setColor(Color3::fromHsv(120.0_degf, 1.0f, 0.7f))); + .setColor(Color3::fromHsv({120.0_degf, 1.0f, 0.7f}))); // Create debug renderer for given object, use "my" options for it Vector3 force; diff --git a/doc/snippets/MagnumMath.cpp b/doc/snippets/MagnumMath.cpp index 779420a83..1f19babfc 100644 --- a/doc/snippets/MagnumMath.cpp +++ b/doc/snippets/MagnumMath.cpp @@ -110,7 +110,7 @@ static_cast(b); /* [matrix-vector-construct-color-hue] */ auto green = Color3::green(); // {0.0f, 1.0f, 0.0f} auto cyan = Color4::cyan(0.5f, 0.95f); // {0.5f, 1.0f, 1.0f, 0.95f} -auto fadedRed = Color3::fromHsv(219.0_degf, 0.50f, 0.57f); +auto fadedRed = Color3::fromHsv({219.0_degf, 0.50f, 0.57f}); /* [matrix-vector-construct-color-hue] */ static_cast(green); static_cast(cyan); @@ -726,15 +726,6 @@ static_cast(a); static_cast(b); } -{ -Color3 color; -/* [Color3-toHsv] */ -Deg hue; -Float saturation, value; -std::tie(hue, saturation, value) = color.toHsv(); -/* [Color3-toHsv] */ -} - { /* [Color3-toSrgb] */ Color3 color; @@ -775,15 +766,6 @@ Color4 rgba = Color4::fromSrgb(0xff3366, 0.5f); static_cast(rgba); } -{ -Color4 color; -/* [Color4-toHsv] */ -Deg hue; -Float saturation, value; -std::tie(hue, saturation, value) = color.toHsv(); -/* [Color4-toHsv] */ -} - { /* [Color4-toSrgbAlpha] */ Color4 color; diff --git a/src/Magnum/Magnum.h b/src/Magnum/Magnum.h index 235391b20..ccd43bd73 100644 --- a/src/Magnum/Magnum.h +++ b/src/Magnum/Magnum.h @@ -311,6 +311,9 @@ typedef Math::Color3 Color3; /** @brief Four-component (RGBA) float color */ typedef Math::Color4 Color4; +/** @brief HSV float color */ +typedef Math::ColorHsv ColorHsv; + /** @brief Three-component (RGB) unsigned byte color diff --git a/src/Magnum/Math/Color.h b/src/Magnum/Math/Color.h index 1ab31d25c..34c46c80e 100644 --- a/src/Magnum/Math/Color.h +++ b/src/Magnum/Math/Color.h @@ -29,45 +29,43 @@ * @brief Class @ref Magnum::Math::Color3, @ref Magnum::Math::Color4, literal @link Magnum::Math::Literals::operator""_rgb() @endlink, @link Magnum::Math::Literals::operator""_rgba() @endlink, @link Magnum::Math::Literals::operator""_rgbf() @endlink, @link Magnum::Math::Literals::operator""_rgbaf() @endlink, @link Magnum::Math::Literals::operator""_srgb() @endlink, @link Magnum::Math::Literals::operator""_srgba() @endlink, @link Magnum::Math::Literals::operator""_srgbf() @endlink, @link Magnum::Math::Literals::operator""_srgbaf() @endlink */ -#include - #include "Magnum/Math/Matrix.h" #include "Magnum/Math/Packing.h" #include "Magnum/Math/Vector4.h" +#ifdef MAGNUM_BUILD_DEPRECATED +#include /** @todo remove when Color[34]::Hsv is removed */ +#endif + namespace Magnum { namespace Math { namespace Implementation { /* Convert color from HSV */ -template typename std::enable_if::value, Color3>::type fromHsv(const typename Color3::Hsv& hsv) { - Deg hue; - T saturation, value; - std::tie(hue, saturation, value) = hsv; - +template typename std::enable_if::value, Color3>::type fromHsv(ColorHsv hsv) { /* Remove repeats */ - hue -= floor(T(hue)/T(360))*Deg(360); - if(hue < Deg(0)) hue += Deg(360); + hsv.hue -= floor(T(hsv.hue)/T(360))*Deg(360); + if(hsv.hue < Deg(0)) hsv.hue += Deg(360); - int h = int(T(hue)/T(60)) % 6; - T f = T(hue)/T(60) - h; + int h = int(T(hsv.hue)/T(60)) % 6; + T f = T(hsv.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); + T p = hsv.value * (T(1) - hsv.saturation); + T q = hsv.value * (T(1) - f*hsv.saturation); + T t = hsv.value * (T(1) - (T(1) - f)*hsv.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}; + case 0: return {hsv.value, t, p}; + case 1: return {q, hsv.value, p}; + case 2: return {p, hsv.value, t}; + case 3: return {p, q, hsv.value}; + case 4: return {t, p, hsv.value}; + case 5: return {hsv.value, p, q}; default: CORRADE_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */ } } -template inline typename std::enable_if::value, Color3>::type fromHsv(const typename Color3::Hsv& hsv) { - return pack>(fromHsv::FloatingPointType>(hsv)); +template inline typename std::enable_if::value, Color3>::type fromHsv(const ColorHsv::FloatingPointType>& hsv) { + return pack>(fromHsv::FloatingPointType>(hsv)); } /* Internal hue computing function */ @@ -114,14 +112,14 @@ template inline typename Color3::FloatingPointType value(typename st } /* Convert color to HSV */ -template inline typename Color3::Hsv toHsv(typename std::enable_if::value, const Color3&>::type color) { +template inline ColorHsv 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); + return ColorHsv{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>(unpack::FloatingPointType>>(color)); +template inline ColorHsv::FloatingPointType> toHsv(typename std::enable_if::value, const Color3&>::type color) { + return toHsv::FloatingPointType>(unpack::FloatingPointType>>(color)); } /* sRGB -> RGB conversion */ @@ -254,13 +252,12 @@ template class Color3: public Vector3 { */ typedef typename TypeTraits::FloatingPointType FloatingPointType; - /** - * @brief Type for storing HSV color space values - * - * Hue in range @f$ [0.0, 360.0] @f$, saturation and value in range - * @f$ [0.0, 1.0] @f$. + #ifdef MAGNUM_BUILD_DEPRECATED + /** @brief @copybrief ColorHsv + * @deprecated Use @ref ColorHsv instead. */ - typedef std::tuple, FloatingPointType, FloatingPointType> Hsv; + typedef CORRADE_DEPRECATED("use ColorHsv instead") std::tuple, FloatingPointType, FloatingPointType> Hsv; + #endif /** * @brief Red color @@ -335,13 +332,18 @@ template class Color3: public Vector3 { * Hue can overflow the range @f$ [0.0, 360.0] @f$. * @see @ref toHsv() */ - static Color3 fromHsv(const Hsv& hsv) { + static Color3 fromHsv(const ColorHsv& hsv) { return Implementation::fromHsv(hsv); } - /** @overload */ - static Color3 fromHsv(Deg hue, FloatingPointType saturation, FloatingPointType value) { - return fromHsv(std::make_tuple(hue, saturation, value)); + + #ifdef MAGNUM_BUILD_DEPRECATED + /** @brief @copybrief fromHsv(const ColorHsv&) + * @deprecated Use @ref fromHsv(const ColorHsv&) instead. + */ + static CORRADE_DEPRECATED("use fromHsv(const ColorHsv&) instead") Color3 fromHsv(Deg hue, FloatingPointType saturation, FloatingPointType value) { + return fromHsv({hue, saturation, value}); } + #endif /** * @brief Create linear RGB color from sRGB representation @@ -482,13 +484,9 @@ template class Color3: public Vector3 { /** * @brief Convert to HSV representation * - * Example usage: - * - * @snippet MagnumMath.cpp Color3-toHsv - * * @see @ref hue(), @ref saturation(), @ref value(), @ref fromHsv() */ - Hsv toHsv() const { + ColorHsv toHsv() const { return Implementation::toHsv(*this); } @@ -616,8 +614,12 @@ class Color4: public Vector4 { /** @copydoc Color3::FloatingPointType */ typedef typename Color3::FloatingPointType FloatingPointType; - /** @copydoc Color3::Hsv */ - typedef typename Color3::Hsv Hsv; + #ifdef MAGNUM_BUILD_DEPRECATED + /** @brief @copybrief ColorHsv + * @deprecated Use @ref ColorHsv instead. + */ + typedef CORRADE_DEPRECATED("use ColorHsv instead") std::tuple, FloatingPointType, FloatingPointType> Hsv; + #endif /** * @brief Red color @@ -689,13 +691,18 @@ class Color4: public Vector4 { * Hue can overflow the range @f$ [0.0, 360.0] @f$. * @see @ref toHsv() */ - static Color4 fromHsv(const Hsv& hsv, T a = Implementation::fullChannel()) { + static Color4 fromHsv(const ColorHsv& hsv, T a = Implementation::fullChannel()) { return Color4(Implementation::fromHsv(hsv), a); } - /** @overload */ - static Color4 fromHsv(Deg hue, FloatingPointType saturation, FloatingPointType value, T alpha = Implementation::fullChannel()) { - return fromHsv(std::make_tuple(hue, saturation, value), alpha); + + #ifdef MAGNUM_BUILD_DEPRECATED + /** @brief @copybrief fromHsv(const ColorHsv&, T) + * @deprecated Use @ref fromHsv(const ColorHsv&, T) instead. + */ + static CORRADE_DEPRECATED("use fromHsv(const ColorHsv&, T) instead") Color4 fromHsv(Deg hue, FloatingPointType saturation, FloatingPointType value, T alpha = Implementation::fullChannel()) { + return fromHsv({hue, saturation, value}, alpha); } + #endif /** * @brief Create linear RGBA color from sRGB + alpha representation @@ -899,13 +906,11 @@ class Color4: public Vector4 { * @brief Convert to HSV representation * * The alpha channel is not subject to any conversion, so it is - * ignored. Example usage: - * - * @snippet MagnumMath.cpp Color4-toHsv - * - * @see @ref hue(), @ref saturation(), @ref value(), @ref fromHsv() + * ignored. + * @see @ref hue(), @ref saturation(), @ref value(), @ref a(), + * @ref fromHsv() */ - Hsv toHsv() const { + ColorHsv toHsv() const { return Implementation::toHsv(Vector4::rgb()); } @@ -1025,6 +1030,100 @@ template inline Vector3 xyzToXyY(const Vector3& xyz) { return {xyz.xy()/xyz.sum(), xyz.y()}; } +/** +@brief HSV color + +Storage-only type with just the usual constructors and (non-)equality +comparison. +@see @ref Color3::fromHsv(), @ref Color3::toHsv(), @ref Color4::fromHsv(), + @ref Color4::toHsv() +*/ +template struct ColorHsv { + /** + * @brief Default constructor + * + * All members are set to zero. + */ + constexpr /*implicit*/ ColorHsv(ZeroInitT = ZeroInit) noexcept: hue{}, saturation{}, value{} {} + + /** @brief Construct without initializing the contents */ + explicit ColorHsv(NoInitT) noexcept: hue{NoInit} /* and the others not */ {} + + /** @brief Constructor */ + constexpr /*implicit*/ ColorHsv(Deg hue, T saturation, T value) noexcept: hue{hue}, saturation{saturation}, value{value} {} + + /** + * @brief Construct from different type + * + * Performs only default casting on the values, no rounding or + * anything else. + */ + template constexpr explicit ColorHsv(const ColorHsv& other) noexcept: hue{other.hue}, saturation{T(other.saturation)}, value{T(other.value)} {} + + #ifdef MAGNUM_BUILD_DEPRECATED + /** + * @brief Construct from @ref Color3::Hsv + * @deprecated Use @ref ColorHsv instead of @ref Color3::Hsv + */ + constexpr CORRADE_DEPRECATED("use ColorHsv instead of Color3::Hsv") /*implicit*/ ColorHsv(std::tuple, T, T> hsv) noexcept: + hue{std::get<0>(hsv)}, saturation{std::get<1>(hsv)}, value{std::get<2>(hsv)} {} + + /** + * @brief Convert to @ref Color3::Hsv + * @deprecated Use @ref ColorHsv instead of @ref Color3::Hsv + */ + constexpr CORRADE_DEPRECATED("use ColorHsv instead of Color3::Hsv") /*implicit*/ operator std::tuple, T, T>() const { + return std::make_tuple(hue, saturation, value); + } + + /** @overload */ /* for std::tie() */ + CORRADE_DEPRECATED("use ColorHsv instead of Color3::Hsv") /*implicit*/ operator std::tuple&, T&, T&>() { + return std::tuple&, T&, T&>{hue, saturation, value}; + } + + /** @overload */ /* for std::tie() */ + constexpr CORRADE_DEPRECATED("use ColorHsv instead of Color3::Hsv") /*implicit*/ operator std::tuple&, const T&, const T&>() const { + return std::tuple&, const T&, const T&>{hue, saturation, value}; + } + #endif + + /** @brief Equality comparison */ + bool operator==(const ColorHsv& other) const { + return hue == other.hue && + TypeTraits::equals(saturation, other.saturation) && + TypeTraits::equals(value, other.value); + } + + /** @brief Non-equality comparison */ + bool operator!=(const ColorHsv& other) const { + return !operator==(other); + } + + /** @brief Hue, in range @f$ [0.0, 360.0] @f$ */ + Deg hue; + + /** @brief Saturation, in range @f$ [0.0, 1.0] @f$ */ + T saturation; + + /** @brief Value, in range @f$ [0.0, 1.0] @f$ */ + T value; +}; + +#ifndef CORRADE_NO_DEBUG +/** @debugoperator{ColorHsv} */ +template Corrade::Utility::Debug& operator<<(Corrade::Utility::Debug& debug, const ColorHsv& value) { + return debug << "ColorHsv(" << Corrade::Utility::Debug::nospace << value.hue + << Corrade::Utility::Debug::nospace << "," << value.saturation + << Corrade::Utility::Debug::nospace << "," << value.value + << Corrade::Utility::Debug::nospace << ")"; +} + +/* Explicit instantiation for commonly used types */ +#ifndef DOXYGEN_GENERATING_OUTPUT +extern template MAGNUM_EXPORT Corrade::Utility::Debug& operator<<(Corrade::Utility::Debug&, const ColorHsv&); +#endif +#endif + #ifndef DOXYGEN_GENERATING_OUTPUT MAGNUM_VECTORn_OPERATOR_IMPLEMENTATION(4, Color4) #endif diff --git a/src/Magnum/Math/Math.h b/src/Magnum/Math/Math.h index 6fe7918e6..accf705dd 100644 --- a/src/Magnum/Math/Math.h +++ b/src/Magnum/Math/Math.h @@ -78,6 +78,7 @@ template class Vector2; template class Vector3; template class Vector4; +template struct ColorHsv; template class Color3; template class Color4; diff --git a/src/Magnum/Math/Test/ColorTest.cpp b/src/Magnum/Math/Test/ColorTest.cpp index d98701765..b8a9cdf7c 100644 --- a/src/Magnum/Math/Test/ColorTest.cpp +++ b/src/Magnum/Math/Test/ColorTest.cpp @@ -83,6 +83,13 @@ struct ColorTest: Corrade::TestSuite::Tester { void constructCopy(); void convert(); + void constructHsv(); + void constructHsvDefault(); + void constructHsvNoInit(); + void constructHsvConversion(); + void constructHsvCopy(); + void compareHsv(); + void data(); void literals(); @@ -114,6 +121,7 @@ struct ColorTest: Corrade::TestSuite::Tester { void swizzleType(); void debug(); void debugUb(); + void debugHsv(); #if defined(DOXYGEN_GENERATING_OUTPUT) || defined(CORRADE_TARGET_UNIX) || (defined(CORRADE_TARGET_WINDOWS) && !defined(CORRADE_TARGET_WINDOWS_RT)) || defined(CORRADE_TARGET_EMSCRIPTEN) void tweakableRgb(); @@ -144,6 +152,8 @@ typedef Math::Vector4 Vector4; typedef Math::Color4 Color4; typedef Math::Color4 Color4ub; +typedef Math::ColorHsv ColorHsv; + typedef Math::Deg Deg; using namespace Literals; @@ -193,6 +203,13 @@ ColorTest::ColorTest() { &ColorTest::constructCopy, &ColorTest::convert, + &ColorTest::constructHsv, + &ColorTest::constructHsvDefault, + &ColorTest::constructHsvNoInit, + &ColorTest::constructHsvConversion, + &ColorTest::constructHsvCopy, + &ColorTest::compareHsv, + &ColorTest::data, &ColorTest::literals, @@ -227,7 +244,8 @@ ColorTest::ColorTest() { &ColorTest::swizzleType, &ColorTest::debug, - &ColorTest::debugUb}); + &ColorTest::debugUb, + &ColorTest::debugHsv}); #if defined(DOXYGEN_GENERATING_OUTPUT) || defined(CORRADE_TARGET_UNIX) || (defined(CORRADE_TARGET_WINDOWS) && !defined(CORRADE_TARGET_WINDOWS_RT)) || defined(CORRADE_TARGET_EMSCRIPTEN) addInstancedTests({&ColorTest::tweakableRgb, @@ -432,6 +450,89 @@ void ColorTest::convert() { CORRADE_VERIFY(!(std::is_convertible::value)); } +void ColorTest::constructHsv() { + ColorHsv a{135.0_degf, 0.5f, 0.9f}; + CORRADE_COMPARE(a.hue, 135.0_degf); + CORRADE_COMPARE(a.saturation, 0.5f); + CORRADE_COMPARE(a.value, 0.9f); + + constexpr ColorHsv ca{135.0_degf, 0.5f, 0.9f}; + constexpr Deg hue = ca.hue; + constexpr Float saturation = ca.saturation; + constexpr Float value = ca.value; + CORRADE_COMPARE(hue, 135.0_degf); + CORRADE_COMPARE(saturation, 0.5f); + CORRADE_COMPARE(value, 0.9f); + + CORRADE_VERIFY((std::is_nothrow_constructible::value)); +} + +void ColorTest::constructHsvDefault() { + ColorHsv a1; + ColorHsv a2{ZeroInit}; + CORRADE_COMPARE(a1, (ColorHsv{0.0_degf, 0.0f, 0.0f})); + CORRADE_COMPARE(a2, (ColorHsv{0.0_degf, 0.0f, 0.0f})); + + constexpr ColorHsv ca1; + constexpr ColorHsv ca2{ZeroInit}; + CORRADE_COMPARE(ca1, (ColorHsv{0.0_degf, 0.0f, 0.0f})); + CORRADE_COMPARE(ca2, (ColorHsv{0.0_degf, 0.0f, 0.0f})); + + CORRADE_VERIFY(std::is_nothrow_default_constructible::value); + CORRADE_VERIFY((std::is_nothrow_constructible::value)); +} + +void ColorTest::constructHsvNoInit() { + ColorHsv a{135.0_degf, 0.5f, 0.9f}; + new(&a) ColorHsv{NoInit}; + CORRADE_COMPARE(a, (ColorHsv{135.0_degf, 0.5f, 0.9f})); + + CORRADE_VERIFY((std::is_nothrow_constructible::value)); + + /* Implicit construction is not allowed */ + CORRADE_VERIFY(!(std::is_convertible::value)); +} + +void ColorTest::constructHsvConversion() { + typedef Math::ColorHsv ColorHsvd; + + /* Converting from double to float and not the other way around because + 0.9f is 0.899999976158142 */ + ColorHsvd a{135.0_deg, 0.5, 0.9}; + ColorHsv b{a}; + CORRADE_COMPARE(b, (ColorHsv(135.0_degf, 0.5f, 0.9f))); + + constexpr ColorHsvd ca{135.0_deg, 0.5, 0.9}; + constexpr ColorHsv cb{ca}; + CORRADE_COMPARE(cb, (ColorHsv(135.0_degf, 0.5f, 0.9f))); + + /* Implicit conversion is not allowed */ + CORRADE_VERIFY(!(std::is_convertible::value)); + + CORRADE_VERIFY((std::is_nothrow_constructible::value)); +} + +void ColorTest::constructHsvCopy() { + ColorHsv a{135.0_degf, 0.5f, 0.9f}; + ColorHsv b{a}; + CORRADE_COMPARE(b, (ColorHsv(135.0_degf, 0.5f, 0.9f))); + + constexpr ColorHsv ca{135.0_degf, 0.5f, 0.9f}; + constexpr ColorHsv cb{ca}; + CORRADE_COMPARE(cb, (ColorHsv(135.0_degf, 0.5f, 0.9f))); + + CORRADE_VERIFY(std::is_nothrow_copy_constructible::value); + CORRADE_VERIFY(std::is_nothrow_copy_assignable::value); +} + +void ColorTest::compareHsv() { + CORRADE_VERIFY((ColorHsv{135.0_degf, 0.5f, 0.9f} == ColorHsv{135.0_degf + Deg(TypeTraits::epsilon()*100.0f), 0.5f, 0.9f})); + CORRADE_VERIFY((ColorHsv{135.0_degf, 0.5f, 0.9f} != ColorHsv{135.0_degf + Deg(TypeTraits::epsilon()*400.0f), 0.5f, 0.9f})); + + CORRADE_VERIFY((ColorHsv{135.0_degf, 0.5f, 0.9f} == ColorHsv{135.0_degf, 0.5f, 0.9f + TypeTraits::epsilon()*0.5f})); + CORRADE_VERIFY((ColorHsv{135.0_degf, 0.5f, 0.9f} != ColorHsv{135.0_degf, 0.5f, 0.9f + TypeTraits::epsilon()*2.0f})); +} + void ColorTest::data() { Color4 c{1.0f, 2.0f, 3.0f, 4.0f}; constexpr const Color4 cc{1.0f, 2.0f, 3.0f, 4.0f}; @@ -514,12 +615,12 @@ void ColorTest::colors() { } void ColorTest::hue() { - CORRADE_COMPARE(Color3::fromHsv( 27.0_degf, 1.0f, 1.0f), (Color3{1.0f, 0.45f, 0.0f})); - CORRADE_COMPARE(Color3::fromHsv( 86.0_degf, 1.0f, 1.0f), (Color3{0.566667f, 1.0f, 0.0f})); - CORRADE_COMPARE(Color3::fromHsv(134.0_degf, 1.0f, 1.0f), (Color3{0.0f, 1.0f, 0.233333f})); - CORRADE_COMPARE(Color3::fromHsv(191.0_degf, 1.0f, 1.0f), (Color3{0.0f, 0.816667f, 1.0f})); - CORRADE_COMPARE(Color3::fromHsv(269.0_degf, 1.0f, 1.0f), (Color3{0.483333f, 0.0f, 1.0f})); - CORRADE_COMPARE(Color3::fromHsv(317.0_degf, 1.0f, 1.0f), (Color3{1.0f, 0.0f, 0.716667f})); + CORRADE_COMPARE(Color3::fromHsv({ 27.0_degf, 1.0f, 1.0f}), (Color3{1.0f, 0.45f, 0.0f})); + CORRADE_COMPARE(Color3::fromHsv({ 86.0_degf, 1.0f, 1.0f}), (Color3{0.566667f, 1.0f, 0.0f})); + CORRADE_COMPARE(Color3::fromHsv({134.0_degf, 1.0f, 1.0f}), (Color3{0.0f, 1.0f, 0.233333f})); + CORRADE_COMPARE(Color3::fromHsv({191.0_degf, 1.0f, 1.0f}), (Color3{0.0f, 0.816667f, 1.0f})); + CORRADE_COMPARE(Color3::fromHsv({269.0_degf, 1.0f, 1.0f}), (Color3{0.483333f, 0.0f, 1.0f})); + CORRADE_COMPARE(Color3::fromHsv({317.0_degf, 1.0f, 1.0f}), (Color3{1.0f, 0.0f, 0.716667f})); CORRADE_COMPARE((Color3{1.0f, 0.45f, 0.0f}).hue(), 27.0_degf); CORRADE_COMPARE((Color3{0.566667f, 1.0f, 0.0f}).hue(), 86.0_degf); @@ -529,20 +630,20 @@ void ColorTest::hue() { CORRADE_COMPARE((Color3{1.0f, 0.0f, 0.716667f}).hue(), 317.0_degf); /* RGBA */ - CORRADE_COMPARE(Color4::fromHsv(27.0_degf, 1.0f, 1.0f, 0.175f), (Color4{1.0f, 0.45f, 0.0f, 0.175f})); + CORRADE_COMPARE(Color4::fromHsv({27.0_degf, 1.0f, 1.0f}, 0.175f), (Color4{1.0f, 0.45f, 0.0f, 0.175f})); CORRADE_COMPARE((Color4{1.0f, 0.45f, 0.0f, 0.175f}).hue(), 27.0_degf); /* Integral -- little precision loss */ - CORRADE_COMPARE(Math::Color3::fromHsv(27.0_degf, 1.0f, 1.0f), + CORRADE_COMPARE(Math::Color3::fromHsv({27.0_degf, 1.0f, 1.0f}), (Math::Color3{65535, 29491, 0})); - CORRADE_COMPARE(Math::Color4::fromHsv(27.0_degf, 1.0f, 1.0f, 15239), + CORRADE_COMPARE(Math::Color4::fromHsv({27.0_degf, 1.0f, 1.0f}, 15239), (Math::Color4{65535, 29491, 0, 15239})); CORRADE_COMPARE((Math::Color3{65535, 29490, 0}).hue(), 26.9993_degf); CORRADE_COMPARE((Math::Color4{65535, 29490, 0, 15239}.hue()), 26.9993_degf); } void ColorTest::saturation() { - CORRADE_COMPARE(Color3::fromHsv(0.0_degf, 0.702f, 1.0f), (Color3{1.0f, 0.298f, 0.298f})); + CORRADE_COMPARE(Color3::fromHsv({0.0_degf, 0.702f, 1.0f}), (Color3{1.0f, 0.298f, 0.298f})); CORRADE_COMPARE((Color3{1.0f, 0.298f, 0.298f}).saturation(), 0.702f); /* Extremes */ @@ -550,20 +651,20 @@ void ColorTest::saturation() { CORRADE_COMPARE((Color3{0.0f, 1.0f, 0.0f}).saturation(), 1.0f); /* RGBA */ - CORRADE_COMPARE(Color4::fromHsv(0.0_degf, 0.702f, 1.0f, 0.175f), (Color4{1.0f, 0.298f, 0.298f, 0.175f})); + CORRADE_COMPARE(Color4::fromHsv({0.0_degf, 0.702f, 1.0f}, 0.175f), (Color4{1.0f, 0.298f, 0.298f, 0.175f})); CORRADE_COMPARE((Color4{1.0f, 0.298f, 0.298f, 0.175f}).saturation(), 0.702f); /* Integral -- little precision loss */ - CORRADE_COMPARE(Math::Color3::fromHsv(0.0_degf, 0.702f, 1.0f), + CORRADE_COMPARE(Math::Color3::fromHsv({0.0_degf, 0.702f, 1.0f}), (Math::Color3{65535, 19529, 19529})); - CORRADE_COMPARE(Math::Color4::fromHsv(0.0_degf, 0.702f, 1.0f, 15239), + CORRADE_COMPARE(Math::Color4::fromHsv({0.0_degf, 0.702f, 1.0f}, 15239), (Math::Color4{65535, 19529, 19529, 15239})); CORRADE_COMPARE((Math::Color3{65535, 19529, 19529}.saturation()), 0.702007f); CORRADE_COMPARE((Math::Color4{65535, 19529, 19529, 15239}.saturation()), 0.702007f); } void ColorTest::value() { - CORRADE_COMPARE(Color3::fromHsv(0.0_degf, 1.0f, 0.522f), (Color3{0.522f, 0.0f, 0.0f})); + CORRADE_COMPARE(Color3::fromHsv({0.0_degf, 1.0f, 0.522f}), (Color3{0.522f, 0.0f, 0.0f})); CORRADE_COMPARE((Color3{0.522f, 0.0f, 0.0f}).value(), 0.522f); /* Extremes */ @@ -571,95 +672,81 @@ void ColorTest::value() { CORRADE_COMPARE((Color3{0.0f, 1.0f, 0.0f}).value(), 1.0f); /* RGBA */ - CORRADE_COMPARE(Color4::fromHsv(0.0_degf, 1.0f, 0.522f, 0.175f), (Color4{0.522f, 0.0f, 0.0f, 0.175f})); + CORRADE_COMPARE(Color4::fromHsv({0.0_degf, 1.0f, 0.522f}, 0.175f), (Color4{0.522f, 0.0f, 0.0f, 0.175f})); CORRADE_COMPARE((Color4{0.522f, 0.0f, 0.0f, 0.175f}).value(), 0.522f); /* Integral -- little precision loss */ - CORRADE_COMPARE(Math::Color3::fromHsv(0.0_degf, 1.0f, 0.522f), + CORRADE_COMPARE(Math::Color3::fromHsv({0.0_degf, 1.0f, 0.522f}), (Math::Color3{34209, 0, 0})); - CORRADE_COMPARE(Math::Color4::fromHsv(0.0_degf, 1.0f, 0.522f, 15239), + CORRADE_COMPARE(Math::Color4::fromHsv({0.0_degf, 1.0f, 0.522f}, 15239), (Math::Color4{34209, 0, 0, 15239})); CORRADE_COMPARE((Math::Color3{34209, 0, 0}.value()), 0.521996f); CORRADE_COMPARE((Math::Color4{34209, 0, 0, 15239}.value()), 0.521996f); } void ColorTest::hsv() { - CORRADE_COMPARE(Color3::fromHsv(std::make_tuple(230.0_degf, 0.749f, 0.427f)), - (Color3{0.107177f, 0.160481f, 0.427f})); - CORRADE_COMPARE(Color3::fromHsv(230.0_degf, 0.749f, 0.427f), + CORRADE_COMPARE(Color3::fromHsv({230.0_degf, 0.749f, 0.427f}), (Color3{0.107177f, 0.160481f, 0.427f})); - Deg hue; - Float saturation, value; - std::tie(hue, saturation, value) = Color3{0.107177f, 0.160481f, 0.427f}.toHsv(); - CORRADE_COMPARE(hue, 230.0_degf); - CORRADE_COMPARE(saturation, 0.749f); - CORRADE_COMPARE(value, 0.427f); + ColorHsv hsv = Color3{0.107177f, 0.160481f, 0.427f}.toHsv(); + CORRADE_COMPARE(hsv.hue, 230.0_degf); + CORRADE_COMPARE(hsv.saturation, 0.749f); + CORRADE_COMPARE(hsv.value, 0.427f); /* RGBA */ - CORRADE_COMPARE(Color4::fromHsv(std::make_tuple(230.0_degf, 0.749f, 0.427f), 0.175f), - (Color4{0.107177f, 0.160481f, 0.427f, 0.175f})); - CORRADE_COMPARE(Color4::fromHsv(230.0_degf, 0.749f, 0.427f, 0.175f), + CORRADE_COMPARE(Color4::fromHsv({230.0_degf, 0.749f, 0.427f}, 0.175f), (Color4{0.107177f, 0.160481f, 0.427f, 0.175f})); - std::tie(hue, saturation, value) = Color4{0.107177f, 0.160481f, 0.427f, 0.175f}.toHsv(); - CORRADE_COMPARE(hue, 230.0_degf); - CORRADE_COMPARE(saturation, 0.749f); - CORRADE_COMPARE(value, 0.427f); + hsv = Color4{0.107177f, 0.160481f, 0.427f, 0.175f}.toHsv(); + CORRADE_COMPARE(hsv.hue, 230.0_degf); + CORRADE_COMPARE(hsv.saturation, 0.749f); + CORRADE_COMPARE(hsv.value, 0.427f); /* Integral -- little precision loss */ - CORRADE_COMPARE(Math::Color3::fromHsv(std::make_tuple(230.0_degf, 0.749f, 0.427f)), - (Math::Color3{7024, 10517, 27983})); - CORRADE_COMPARE(Math::Color3::fromHsv(230.0_degf, 0.749f, 0.427f), + CORRADE_COMPARE(Math::Color3::fromHsv({230.0_degf, 0.749f, 0.427f}), (Math::Color3{7024, 10517, 27983})); - CORRADE_COMPARE(Math::Color4::fromHsv(std::make_tuple(230.0_degf, 0.749f, 0.427f), 15239), - (Math::Color4{7024, 10517, 27983, 15239})); - CORRADE_COMPARE(Math::Color4::fromHsv(230.0_degf, 0.749f, 0.427f, 15239), + CORRADE_COMPARE(Math::Color4::fromHsv({230.0_degf, 0.749f, 0.427f}, 15239), (Math::Color4{7024, 10517, 27983, 15239})); - std::tie(hue, saturation, value) = Math::Color3{7023, 10517, 27983}.toHsv(); - CORRADE_COMPARE(hue, 230.0_degf); - CORRADE_COMPARE(saturation, 0.749026f); - CORRADE_COMPARE(value, 0.426993f); + hsv = Math::Color3{7023, 10517, 27983}.toHsv(); + CORRADE_COMPARE(hsv.hue, 230.0_degf); + CORRADE_COMPARE(hsv.saturation, 0.749026f); + CORRADE_COMPARE(hsv.value, 0.426993f); - std::tie(hue, saturation, value) = Math::Color4{7023, 10517, 27983, 15239}.toHsv(); - CORRADE_COMPARE(hue, 230.0_degf); - CORRADE_COMPARE(saturation, 0.749026f); - CORRADE_COMPARE(value, 0.426993f); + hsv = Math::Color4{7023, 10517, 27983, 15239}.toHsv(); + CORRADE_COMPARE(hsv.hue, 230.0_degf); + CORRADE_COMPARE(hsv.saturation, 0.749026f); + CORRADE_COMPARE(hsv.value, 0.426993f); /* Round-trip */ - CORRADE_COMPARE(Color3::fromHsv(230.0_degf, 0.749f, 0.427f).toHsv(), - std::make_tuple(230.0_degf, 0.749f, 0.427f)); - CORRADE_COMPARE(Color4::fromHsv(230.0_degf, 0.749f, 0.427f, 0.175f).toHsv(), - std::make_tuple(230.0_degf, 0.749f, 0.427f)); + CORRADE_COMPARE(Color3::fromHsv({230.0_degf, 0.749f, 0.427f}).toHsv(), + (ColorHsv{230.0_degf, 0.749f, 0.427f})); + CORRADE_COMPARE(Color4::fromHsv({230.0_degf, 0.749f, 0.427f}, 0.175f).toHsv(), + (ColorHsv{230.0_degf, 0.749f, 0.427f})); } void ColorTest::fromHsvHueOverflow() { - CORRADE_COMPARE(Color3::fromHsv( 27.0_degf - 360.0_degf, 1.0f, 1.0f), (Color3{1.0f, 0.45f, 0.0f})); - CORRADE_COMPARE(Color3::fromHsv( 86.0_degf - 360.0_degf, 1.0f, 1.0f), (Color3{0.566667f, 1.0f, 0.0f})); - CORRADE_COMPARE(Color3::fromHsv(134.0_degf - 360.0_degf, 1.0f, 1.0f), (Color3{0.0f, 1.0f, 0.233333f})); - CORRADE_COMPARE(Color3::fromHsv(191.0_degf - 360.0_degf, 1.0f, 1.0f), (Color3{0.0f, 0.816667f, 1.0f})); - CORRADE_COMPARE(Color3::fromHsv(269.0_degf - 360.0_degf, 1.0f, 1.0f), (Color3{0.483333f, 0.0f, 1.0f})); - CORRADE_COMPARE(Color3::fromHsv(317.0_degf - 360.0_degf, 1.0f, 1.0f), (Color3{1.0f, 0.0f, 0.716667f})); - - CORRADE_COMPARE(Color3::fromHsv( 27.0_degf + 360.0_degf, 1.0f, 1.0f), (Color3{1.0f, 0.45f, 0.0f})); - CORRADE_COMPARE(Color3::fromHsv( 86.0_degf + 360.0_degf, 1.0f, 1.0f), (Color3{0.566667f, 1.0f, 0.0f})); - CORRADE_COMPARE(Color3::fromHsv(134.0_degf + 360.0_degf, 1.0f, 1.0f), (Color3{0.0f, 1.0f, 0.233333f})); - CORRADE_COMPARE(Color3::fromHsv(191.0_degf + 360.0_degf, 1.0f, 1.0f), (Color3{0.0f, 0.816667f, 1.0f})); - CORRADE_COMPARE(Color3::fromHsv(269.0_degf + 360.0_degf, 1.0f, 1.0f), (Color3{0.483333f, 0.0f, 1.0f})); - CORRADE_COMPARE(Color3::fromHsv(317.0_degf + 360.0_degf, 1.0f, 1.0f), (Color3{1.0f, 0.0f, 0.716667f})); + CORRADE_COMPARE(Color3::fromHsv({ 27.0_degf - 360.0_degf, 1.0f, 1.0f}), (Color3{1.0f, 0.45f, 0.0f})); + CORRADE_COMPARE(Color3::fromHsv({ 86.0_degf - 360.0_degf, 1.0f, 1.0f}), (Color3{0.566667f, 1.0f, 0.0f})); + CORRADE_COMPARE(Color3::fromHsv({134.0_degf - 360.0_degf, 1.0f, 1.0f}), (Color3{0.0f, 1.0f, 0.233333f})); + CORRADE_COMPARE(Color3::fromHsv({191.0_degf - 360.0_degf, 1.0f, 1.0f}), (Color3{0.0f, 0.816667f, 1.0f})); + CORRADE_COMPARE(Color3::fromHsv({269.0_degf - 360.0_degf, 1.0f, 1.0f}), (Color3{0.483333f, 0.0f, 1.0f})); + CORRADE_COMPARE(Color3::fromHsv({317.0_degf - 360.0_degf, 1.0f, 1.0f}), (Color3{1.0f, 0.0f, 0.716667f})); + + CORRADE_COMPARE(Color3::fromHsv({ 27.0_degf + 360.0_degf, 1.0f, 1.0f}), (Color3{1.0f, 0.45f, 0.0f})); + CORRADE_COMPARE(Color3::fromHsv({ 86.0_degf + 360.0_degf, 1.0f, 1.0f}), (Color3{0.566667f, 1.0f, 0.0f})); + CORRADE_COMPARE(Color3::fromHsv({134.0_degf + 360.0_degf, 1.0f, 1.0f}), (Color3{0.0f, 1.0f, 0.233333f})); + CORRADE_COMPARE(Color3::fromHsv({191.0_degf + 360.0_degf, 1.0f, 1.0f}), (Color3{0.0f, 0.816667f, 1.0f})); + CORRADE_COMPARE(Color3::fromHsv({269.0_degf + 360.0_degf, 1.0f, 1.0f}), (Color3{0.483333f, 0.0f, 1.0f})); + CORRADE_COMPARE(Color3::fromHsv({317.0_degf + 360.0_degf, 1.0f, 1.0f}), (Color3{1.0f, 0.0f, 0.716667f})); } void ColorTest::fromHsvDefaultAlpha() { - CORRADE_COMPARE(Color4::fromHsv(std::make_tuple(230.0_degf, 0.749f, 0.427f)), - (Color4{0.107177f, 0.160481f, 0.427f, 1.0f})); - CORRADE_COMPARE(Color4::fromHsv(230.0_degf, 0.749f, 0.427f), + CORRADE_COMPARE(Color4::fromHsv({230.0_degf, 0.749f, 0.427f}), (Color4{0.107177f, 0.160481f, 0.427f, 1.0f})); /* Integral */ - CORRADE_COMPARE(Math::Color4::fromHsv(std::make_tuple(230.0_degf, 0.749f, 0.427f)), - (Math::Color4{7024, 10517, 27983, 65535})); - CORRADE_COMPARE(Math::Color4::fromHsv(230.0_degf, 0.749f, 0.427f), + CORRADE_COMPARE(Math::Color4::fromHsv({230.0_degf, 0.749f, 0.427f}), (Math::Color4{7024, 10517, 27983, 65535})); } @@ -924,6 +1011,12 @@ void ColorTest::debugUb() { CORRADE_COMPARE(o.str(), "#12345678 #90abcdef\n"); } +void ColorTest::debugHsv() { + std::ostringstream out; + Debug{&out} << ColorHsv(135.0_degf, 0.75f, 0.3f); + CORRADE_COMPARE(out.str(), "ColorHsv(Deg(135), 0.75, 0.3)\n"); +} + #if defined(DOXYGEN_GENERATING_OUTPUT) || defined(CORRADE_TARGET_UNIX) || (defined(CORRADE_TARGET_WINDOWS) && !defined(CORRADE_TARGET_WINDOWS_RT)) || defined(CORRADE_TARGET_EMSCRIPTEN) void ColorTest::tweakableRgb() { auto&& data = TweakableData[testCaseInstanceId()]; diff --git a/src/Magnum/Math/instantiation.cpp b/src/Magnum/Math/instantiation.cpp index 1282dd920..d74280d7a 100644 --- a/src/Magnum/Math/instantiation.cpp +++ b/src/Magnum/Math/instantiation.cpp @@ -126,6 +126,8 @@ template Corrade::Utility::Debug& operator<<(Corrade::Utility::Debug&, const Dua template Corrade::Utility::Debug& operator<<(Corrade::Utility::Debug&, const Quaternion&); template Corrade::Utility::Debug& operator<<(Corrade::Utility::Debug&, const Quaternion&); +template Corrade::Utility::Debug& operator<<(Corrade::Utility::Debug&, const ColorHsv&); + /* Check proper size of GL types */ static_assert(sizeof(Vector<2, Float>) == 8, "Improper size of 2-element Float vector"); static_assert(sizeof(Vector<3, Float>) == 12, "Improper size of 3-element Float vector");