#ifndef BWIDGETS_COLOR_HPP #define BWIDGETS_COLOR_HPP #include #include #include #include #include namespace bwidgets { class Color final { public: [[nodiscard]] inline auto& operator()() { return sdl_type; } [[nodiscard]] inline const auto& operator()() const { return sdl_type; } private: bool _operate_on_alpha; bool _operate_on_colors; template inline auto _operate(const N& operand, const std::function& operator_) const { Color c(sdl_type, _operate_on_alpha, _operate_on_colors); if (_operate_on_alpha) { auto a = std::round(operator_(c().a, operand)); SDL_assert_release(a == (uint8_t)a); // NOLINT c().a = (uint8_t)a; } if (_operate_on_colors) { auto r = std::round(operator_(c().r, operand)); auto g = std::round(operator_(c().g, operand)); auto b = std::round(operator_(c().b, operand)); // NOLINTNEXTLINE SDL_assert_release(r == (uint8_t)r && g == (uint8_t)g && b == (uint8_t)b); c().r = (uint8_t)r; c().g = (uint8_t)g; c().b = (uint8_t)b; } return c; } public: SDL_Color sdl_type; inline Color(uint8_t r, uint8_t g, uint8_t b, uint8_t a, bool op_on_alpha = false, bool op_on_colors = true) noexcept : _operate_on_alpha(op_on_alpha), _operate_on_colors(op_on_colors), sdl_type({r, g, b, a}) {} inline Color(const SDL_Color& c = {}, bool op_on_alpha = false, bool op_on_colors = true) noexcept : _operate_on_alpha(op_on_alpha), _operate_on_colors(op_on_colors), sdl_type(c) {} inline Color(const Color&) noexcept = default; [[nodiscard]] inline auto alpha() const -> Color { return {sdl_type, _operate_on_colors, true}; } [[nodiscard]] inline auto colors() const -> Color { return {sdl_type, true, _operate_on_alpha}; } template [[nodiscard]] inline auto operator+(const N& operand) const { return _operate(operand, [](const N& a, const N& b) { return a + b; }); } template [[nodiscard]] inline auto operator-(const N& operand) const { return _operate(operand, [](const N& a, const N& b) { return a - b; }); } template [[nodiscard]] inline auto operator*(const N& operand) const { return _operate(operand, [](const N& a, const N& b) { return a * b; }); } template [[nodiscard]] inline auto operator/(const N& operand) const { SDL_assert(operand != 0); // NOLINT return _operate(operand, [](const N& a, const N& b) { return a / b; }); } inline auto& operator=(const Color& c) { if (this != &c) { sdl_type = c.sdl_type; } return *this; } inline auto& operator=(const SDL_Color& c) { sdl_type = c; return *this; } [[nodiscard]] inline auto operator==(const Color& other) const { return (_operate_on_colors && sdl_type.r == other().r && sdl_type.g == other().g && sdl_type.b == other().b) || (_operate_on_alpha && sdl_type.a == other().a); } [[nodiscard]] inline auto operator!=(const Color& other) const { return (sdl_type.r != other().r || sdl_type.g != other().g || sdl_type.b != other().b) && ((_operate_on_alpha && sdl_type.a != other().a) || !_operate_on_alpha); } }; } #endif