diff --git a/include/pd/core/color.hpp b/include/pd/core/color.hpp index 2d1c3c7..b750470 100644 --- a/include/pd/core/color.hpp +++ b/include/pd/core/color.hpp @@ -1,231 +1,231 @@ -#pragma once - -/* -MIT License - -Copyright (c) 2024 - 2025 tobid7 - -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 - -namespace PD { -/** - * Color class - * - * - Supports hex input starting with a # and 6 or 8 digits - * - Supports rgb(a) 8Bit unsigned number input - * - Supports rgb(a) float input from 0.0 to 1.0 - * - Supports 32Bit input color - * @note Safetey checks are disabled for maximum performance - */ -class PD_CORE_API Color { - private: - /** Red Value */ - u8 m_r; - /** Green Value */ - u8 m_g; - /** Blue Value */ - u8 m_b; - /** Alpha Value */ - u8 m_a; - - public: - /** - * Default Constructor (all variables are set to 0) - */ - // Color() : m_r(0), m_g(0), m_b(0), m_a(0) {} - constexpr Color() : m_r(0), m_g(0), m_b(0), m_a(0) {} - constexpr ~Color() {} - /** - * Constructor for 32Bit Color Input - * @param color 32Bit Color value - */ - constexpr Color(u32 color) { - m_a = (color >> 24) & 0xff; - m_b = (color >> 16) & 0xff; - m_g = (color >> 8) & 0xff; - m_r = color & 0xff; - } - /** - * Constructor for 8Bit Input - * @param r Red Value - * @param g Green Value - * @param b Blue Value - * @param a Optional Alpha Value (Defaults to 255) - */ - constexpr Color(int r, int g, int b, int a = 255) { - m_r = r; - m_g = g; - m_b = b; - m_a = a; - } - /** - * Constructor for float Input - * @param r Red Value - * @param g Green Value - * @param b Blue Value - * @param a Optional Alpha Value (Defaults to 1.0f) - * @note There is no Check if the number is between 0.0 and 1.0 - */ - constexpr Color(float r, float g, float b, float a = 1.f) { - m_r = static_cast(255.f * r); - m_g = static_cast(255.f * g); - m_b = static_cast(255.f * b); - m_a = static_cast(255.f * a); - } - /** - * Constructor for Hex Input - * @param hex Hex String in `#ffffff` or `#ffffffff` format - */ - Color(const std::string& hex) { Hex(hex); } - /** - * Unused Deconstructor - */ - // ~Color() {} - - /** - * Create Color Object by Hex String - * @param hex Hex String in `#ffffff` or `#ffffffff` format - * @return Color class itself - */ - Color& Hex(const std::string& hex); - /** - * Convert this Color Object to Hex string - * @param rgba [default false] sets if 8 or 6 digit color should be returned - * @return Color Hex String - */ - std::string Hex(bool rgba = false) const; - - /** - * Setter for Red - * @param v value - * @return Color class reference - */ - Color& r(u8 v) { - m_r = v; - return *this; - } - /** - * Getter for Red - * @return Red Value - */ - u8 r() const { return m_r; } - /** - * Setter for Green - * @param v value - * @return Color class reference - */ - Color& g(u8 v) { - m_g = v; - return *this; - } - /** - * Getter for Green - * @return Green Value - */ - u8 g() const { return m_r; } - /** - * Setter for Blue - * @param v value - * @return Color class reference - */ - Color& b(u8 v) { - m_b = v; - return *this; - } - /** - * Getter for Blue - * @return Blue Value - */ - u8 b() const { return m_r; } - /** - * Setter for Alpha - * @param v value - * @return Color class reference - */ - Color& a(u8 v) { - m_a = v; - return *this; - } - /** - * Getter for Alpha - * @return Alpha Value - */ - u8 a() const { return m_r; } - - /** - * Fade from Current to another Color - * @param color Color to fade to - * @param p Amount (supports -1.0 to 1.0 for use of sine) - * @return Class Reference - */ - Color& Fade(const Color& color, float p) { - m_a = static_cast((color.a() - m_a) * ((p + 1.f) / 2)); - m_b = static_cast((color.b() - m_b) * ((p + 1.f) / 2)); - m_g = static_cast((color.g() - m_g) * ((p + 1.f) / 2)); - m_r = static_cast((color.r() - m_r) * ((p + 1.f) / 2)); - return *this; - } - /** - * Get 32Bit Color Value - * @return 32Bit Color Value - */ - u32 Get() const { return (m_a << 24) | (m_b << 16) | (m_g << 8) | m_r; } - /** - * Get The Luminance of the Color - * @return luminance (from 0.0 to 1.0) - */ - float Luminance() const { - // For Reference https://en.wikipedia.org/wiki/HSL_and_HSV#Lightness - return (0.3 * (m_r / 255.f) + 0.59 * (m_g / 255.f) + 0.11 * (m_b / 255.f)); - } - /** - * Check if the Color is Light or Dark - * @return true if light - */ - bool IsLight() const { return (Luminance() >= 0.5); } - - /** - * Operator to cast Color to 32Bit Value - * @return 32Bit Color Value - */ - operator u32() const { return Get(); } -}; -namespace Colors { -constexpr Color White = Color(1.f, 1.f, 1.f, 1.f); -constexpr Color Black = Color(0.f, 0.f, 0.f, 1.f); -constexpr Color Red = Color(1.f, 0.f, 0.f, 1.f); -constexpr Color Green = Color(0.f, 1.f, 0.f, 1.f); -constexpr Color Blue = Color(0.f, 0.f, 1.f, 1.f); -constexpr Color Yellow = Color(1.f, 1.f, 0.f, 1.f); -constexpr Color Cyan = Color(0.f, 1.f, 1.f, 1.f); -constexpr Color Magenta = Color(1.f, 0.f, 1.f, 1.f); -constexpr Color Gray = Color(0.5f, 0.5f, 0.5f, 1.f); -constexpr Color LightGray = Color(0.75f, 0.75f, 0.75f, 1.f); -constexpr Color DarkGray = Color(0.25f, 0.25f, 0.25f, 1.f); -constexpr Color Orange = Color(1.f, 0.65f, 0.f, 1.f); -constexpr Color Pink = Color(1.f, 0.75f, 0.8f, 1.f); -constexpr Color Brown = Color(0.6f, 0.4f, 0.2f, 1.f); -constexpr Color Purple = Color(0.5f, 0.f, 0.5f, 1.f); -constexpr Color Teal = Color(0.f, 0.5f, 0.5f, 1.f); -constexpr Color Transparent = Color(0.f, 0.f, 0.f, 0.f); -} // namespace Colors +#pragma once + +/* +MIT License + +Copyright (c) 2024 - 2025 tobid7 + +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 + +namespace PD { +/** + * Color class + * + * - Supports hex input starting with a # and 6 or 8 digits + * - Supports rgb(a) 8Bit unsigned number input + * - Supports rgb(a) float input from 0.0 to 1.0 + * - Supports 32Bit input color + * @note Safetey checks are disabled for maximum performance + */ +class PD_CORE_API Color { + private: + /** Red Value */ + u8 m_r; + /** Green Value */ + u8 m_g; + /** Blue Value */ + u8 m_b; + /** Alpha Value */ + u8 m_a; + + public: + /** + * Default Constructor (all variables are set to 0) + */ + // Color() : m_r(0), m_g(0), m_b(0), m_a(0) {} + constexpr Color() : m_r(0), m_g(0), m_b(0), m_a(0) {} + constexpr ~Color() {} + /** + * Constructor for 32Bit Color Input + * @param color 32Bit Color value + */ + constexpr Color(u32 color) { + m_a = (color >> 24) & 0xff; + m_b = (color >> 16) & 0xff; + m_g = (color >> 8) & 0xff; + m_r = color & 0xff; + } + /** + * Constructor for 8Bit Input + * @param r Red Value + * @param g Green Value + * @param b Blue Value + * @param a Optional Alpha Value (Defaults to 255) + */ + constexpr Color(int r, int g, int b, int a = 255) { + m_r = r; + m_g = g; + m_b = b; + m_a = a; + } + /** + * Constructor for float Input + * @param r Red Value + * @param g Green Value + * @param b Blue Value + * @param a Optional Alpha Value (Defaults to 1.0f) + * @note There is no Check if the number is between 0.0 and 1.0 + */ + constexpr Color(float r, float g, float b, float a = 1.f) { + m_r = static_cast(255.f * r); + m_g = static_cast(255.f * g); + m_b = static_cast(255.f * b); + m_a = static_cast(255.f * a); + } + /** + * Constructor for Hex Input + * @param hex Hex String in `#ffffff` or `#ffffffff` format + */ + Color(const std::string& hex) { Hex(hex); } + /** + * Unused Deconstructor + */ + // ~Color() {} + + /** + * Create Color Object by Hex String + * @param hex Hex String in `#ffffff` or `#ffffffff` format + * @return Color class itself + */ + Color& Hex(const std::string& hex); + /** + * Convert this Color Object to Hex string + * @param rgba [default false] sets if 8 or 6 digit color should be returned + * @return Color Hex String + */ + std::string Hex(bool rgba = false) const; + + /** + * Setter for Red + * @param v value + * @return Color class reference + */ + Color& r(u8 v) { + m_r = v; + return *this; + } + /** + * Getter for Red + * @return Red Value + */ + u8 r() const { return m_r; } + /** + * Setter for Green + * @param v value + * @return Color class reference + */ + Color& g(u8 v) { + m_g = v; + return *this; + } + /** + * Getter for Green + * @return Green Value + */ + u8 g() const { return m_g; } + /** + * Setter for Blue + * @param v value + * @return Color class reference + */ + Color& b(u8 v) { + m_b = v; + return *this; + } + /** + * Getter for Blue + * @return Blue Value + */ + u8 b() const { return m_b; } + /** + * Setter for Alpha + * @param v value + * @return Color class reference + */ + Color& a(u8 v) { + m_a = v; + return *this; + } + /** + * Getter for Alpha + * @return Alpha Value + */ + u8 a() const { return m_a; } + + /** + * Fade from Current to another Color + * @param color Color to fade to + * @param p Amount (supports -1.0 to 1.0 for use of sine) + * @return Class Reference + */ + Color& Fade(const Color& color, float p) { + m_a = static_cast((color.a() - m_a) * ((p + 1.f) / 2)); + m_b = static_cast((color.b() - m_b) * ((p + 1.f) / 2)); + m_g = static_cast((color.g() - m_g) * ((p + 1.f) / 2)); + m_r = static_cast((color.r() - m_r) * ((p + 1.f) / 2)); + return *this; + } + /** + * Get 32Bit Color Value + * @return 32Bit Color Value + */ + u32 Get() const { return (m_a << 24) | (m_b << 16) | (m_g << 8) | m_r; } + /** + * Get The Luminance of the Color + * @return luminance (from 0.0 to 1.0) + */ + float Luminance() const { + // For Reference https://en.wikipedia.org/wiki/HSL_and_HSV#Lightness + return (0.3 * (m_r / 255.f) + 0.59 * (m_g / 255.f) + 0.11 * (m_b / 255.f)); + } + /** + * Check if the Color is Light or Dark + * @return true if light + */ + bool IsLight() const { return (Luminance() >= 0.5); } + + /** + * Operator to cast Color to 32Bit Value + * @return 32Bit Color Value + */ + operator u32() const { return Get(); } +}; +namespace Colors { +constexpr Color White = Color(1.f, 1.f, 1.f, 1.f); +constexpr Color Black = Color(0.f, 0.f, 0.f, 1.f); +constexpr Color Red = Color(1.f, 0.f, 0.f, 1.f); +constexpr Color Green = Color(0.f, 1.f, 0.f, 1.f); +constexpr Color Blue = Color(0.f, 0.f, 1.f, 1.f); +constexpr Color Yellow = Color(1.f, 1.f, 0.f, 1.f); +constexpr Color Cyan = Color(0.f, 1.f, 1.f, 1.f); +constexpr Color Magenta = Color(1.f, 0.f, 1.f, 1.f); +constexpr Color Gray = Color(0.5f, 0.5f, 0.5f, 1.f); +constexpr Color LightGray = Color(0.75f, 0.75f, 0.75f, 1.f); +constexpr Color DarkGray = Color(0.25f, 0.25f, 0.25f, 1.f); +constexpr Color Orange = Color(1.f, 0.65f, 0.f, 1.f); +constexpr Color Pink = Color(1.f, 0.75f, 0.8f, 1.f); +constexpr Color Brown = Color(0.6f, 0.4f, 0.2f, 1.f); +constexpr Color Purple = Color(0.5f, 0.f, 0.5f, 1.f); +constexpr Color Teal = Color(0.f, 0.5f, 0.5f, 1.f); +constexpr Color Transparent = Color(0.f, 0.f, 0.f, 0.f); +} // namespace Colors } // namespace PD \ No newline at end of file diff --git a/source/core/color.cpp b/source/core/color.cpp index d86ed21..f9e2e27 100644 --- a/source/core/color.cpp +++ b/source/core/color.cpp @@ -1,72 +1,73 @@ -/* -MIT License - -Copyright (c) 2024 - 2025 tobid7 - -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 - -namespace PD { -// The Solution of the biggest performance issue -// A Simple Lookup table -static const std::map HEX_DEC = { - {'0', 0}, {'1', 1}, {'2', 2}, {'3', 3}, {'4', 4}, {'5', 5}, - {'6', 6}, {'7', 7}, {'8', 8}, {'9', 9}, {'a', 10}, {'b', 11}, - {'c', 12}, {'d', 13}, {'e', 14}, {'f', 15}, {'A', 10}, {'B', 11}, - {'C', 12}, {'D', 13}, {'E', 14}, {'F', 15}}; - -PD_CORE_API Color& Color::Hex(const std::string& hex) { -#ifdef PD_NO_SAFE_CODE - /// Safetey check (not required if you programm well xd) - if (hex.length() != 7 || hex.length() != 9 || hex.length() != 6 || - hex.length() != 8 || std::find_if(hex.begin(), hex.end(), [](char c) { - return !std::isxdigit(c); - }) != hex.end()) { - return *this; - } -#endif - int offset = ((hex.length() == 7 || hex.length() == 9) ? 1 : 0); - m_r = HEX_DEC.at(hex[offset]) * 16 + HEX_DEC.at(hex[offset + 1]); - offset += 2; - m_g = HEX_DEC.at(hex[offset]) * 16 + HEX_DEC.at(hex[offset + 1]); - offset += 2; - m_b = HEX_DEC.at(hex[offset]) * 16 + HEX_DEC.at(hex[offset + 1]); - offset += 2; - if (hex.length() == 9) { - m_a = HEX_DEC.at(hex[offset]) * 16 + HEX_DEC.at(hex[offset + 1]); - } else { - m_a = 255; - } - return *this; -} - -PD_CORE_API std::string Color::Hex(bool rgba) const { - std::stringstream s; - s << "#"; - s << std::hex << std::setw(2) << std::setfill('0') << m_r; - s << std::hex << std::setw(2) << std::setfill('0') << m_g; - s << std::hex << std::setw(2) << std::setfill('0') << m_b; - if (rgba) { - s << std::hex << std::setw(2) << std::setfill('0') << m_a; - } - return s.str(); -} +/* +MIT License + +Copyright (c) 2024 - 2025 tobid7 + +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 + +namespace PD { +// The Solution of the biggest performance issue +// A Simple Lookup table +static const std::map HEX_DEC = { + {'0', 0}, {'1', 1}, {'2', 2}, {'3', 3}, {'4', 4}, {'5', 5}, + {'6', 6}, {'7', 7}, {'8', 8}, {'9', 9}, {'a', 10}, {'b', 11}, + {'c', 12}, {'d', 13}, {'e', 14}, {'f', 15}, {'A', 10}, {'B', 11}, + {'C', 12}, {'D', 13}, {'E', 14}, {'F', 15}}; + +PD_CORE_API Color& Color::Hex(const std::string& hex) { +#ifdef PD_NO_SAFE_CODE + /// Safetey check (not required if you programm well xd) + if (hex.length() != 7 || hex.length() != 9 || hex.length() != 6 || + hex.length() != 8 || std::find_if(hex.begin(), hex.end(), [](char c) { + return !std::isxdigit(c); + }) != hex.end()) { + return *this; + } +#endif + int offset = ((hex.length() == 7 || hex.length() == 9) ? 1 : 0); + m_r = HEX_DEC.at(hex[offset]) * 16 + HEX_DEC.at(hex[offset + 1]); + offset += 2; + m_g = HEX_DEC.at(hex[offset]) * 16 + HEX_DEC.at(hex[offset + 1]); + offset += 2; + m_b = HEX_DEC.at(hex[offset]) * 16 + HEX_DEC.at(hex[offset + 1]); + offset += 2; + if (hex.length() == 9) { + m_a = HEX_DEC.at(hex[offset]) * 16 + HEX_DEC.at(hex[offset + 1]); + } else { + m_a = 255; + } + return *this; +} + +PD_CORE_API std::string Color::Hex(bool rgba) const { + /** Need to int cast (so it is used as num and not char...) */ + std::stringstream s; + s << "#"; + s << std::hex << std::setw(2) << std::setfill('0') << (int)m_r; + s << std::hex << std::setw(2) << std::setfill('0') << (int)m_g; + s << std::hex << std::setw(2) << std::setfill('0') << (int)m_b; + if (rgba) { + s << std::hex << std::setw(2) << std::setfill('0') << (int)m_a; + } + return s.str(); +} } // namespace PD \ No newline at end of file