color.h File Reference

Go to the documentation of this file. Source: include/ffw/gui/color.h

/* This file is part of FineFramework project */
#ifndef FFW_COLOR
#define FFW_COLOR

#include <ostream>
#include <math.h>
#include <algorithm>

namespace ffw {
    struct Color {
    public:
        float r;
        float g;
        float b;
        float a;
        inline Color() {
            r = 0;
            g = 0;
            b = 0;
            a = 0;
        }
        inline Color(float red, float green, float blue, float alpha) {
            r = red;
            g = green;
            b = blue;
            a = alpha;
        }
        inline Color(float val, float alpha) {
            r = val;
            g = val;
            b = val;
            a = alpha;
        }
        inline Color(const Color& vec) {
            r = vec.r;
            g = vec.g;
            b = vec.b;
            a = vec.a;
        }
        inline Color(const std::initializer_list<float>& list) {
            if (list.size() != 4) {
                r = 0;
                g = 0;
                b = 0;
                a = 0;
                return;
            }
            r = *(list.begin());
            g = *(list.begin() + 1);
            b = *(list.begin() + 2);
            a = *(list.begin() + 3);
        }
        inline void set(float red, float green, float blue, float alpha) {
            r = red;
            g = green;
            b = blue;
            a = alpha;
        }
        inline void set(float val, float alpha) {
            r = val;
            g = val;
            b = val;
            a = alpha;
        }
        inline void set(const Color& vec) {
            r = vec.r;
            g = vec.g;
            b = vec.b;
            a = vec.a;
        }
        inline void set(const std::initializer_list<float>& list) {
            if (list.size() != 4)return;
            r = *(list.begin());
            g = *(list.begin() + 1);
            b = *(list.begin() + 2);
            a = *(list.begin() + 3);
        }
        inline ffw::Color  operator - () const {
            return Color(-r, -g, -b, -a);
        }
        inline ffw::Color& operator =  (const Color& vec) {
            r = vec.r;
            g = vec.g;
            b = vec.b;
            a = vec.a;
            return *this;
        }
        inline ffw::Color  operator +  (const Color& vec) const {
            return Color(r + vec.r, g + vec.g, b + vec.b, a + vec.a);
        }
        inline ffw::Color& operator += (const Color& vec) {
            r += vec.r;
            g += vec.g;
            b += vec.b;
            a += vec.a;
            return *this;
        }
        inline ffw::Color  operator -  (const Color& vec) const {
            return Color(r - vec.r, g - vec.g, b - vec.b, a - vec.a);
        }
        inline ffw::Color& operator -= (const Color& vec) {
            r -= vec.r;
            g -= vec.g;
            b -= vec.b;
            a -= vec.a;
            return *this;
        }

        inline ffw::Color  operator /  (const Color& vec) const {
            return Color(r / vec.r, g / vec.g, b / vec.b, a / vec.a);
        }

        inline ffw::Color& operator /= (const Color& vec) {
            r /= vec.r;
            g /= vec.g;
            b /= vec.b;
            a /= vec.a;
            return *this;
        }

        inline ffw::Color  operator *  (const Color& vec) const {
            return Color(r * vec.r, g * vec.g, b * vec.b, a * vec.a);
        }

        inline ffw::Color& operator *= (const Color& vec) {
            r *= vec.r;
            g *= vec.g;
            b *= vec.b;
            a *= vec.a;
            return *this;
        }
        inline ffw::Color& operator =  (const float& val) {
            r = val;
            g = val;
            b = val;
            a = val;
            return *this;
        }
        inline ffw::Color  operator +  (const float& val) const {
            return Color(r + val, g + val, b + val, a + val);
        }
        inline ffw::Color& operator += (const float& val) {
            r += val;
            g += val;
            b += val;
            a += val;
            return *this;
        }
        inline ffw::Color  operator -  (const float& val) const {
            return Color(r - val, g - val, b - val, a - val);
        }
        inline ffw::Color& operator -= (const float& val) {
            r -= val;
            g -= val;
            b -= val;
            a -= val;
            return *this;
        }

        inline ffw::Color  operator /  (const float& val) const {
            return Color(r / val, g / val, b / val, a / val);
        }

        inline ffw::Color& operator /= (const float& val) {
            r /= val;
            g /= val;
            b /= val;
            a /= val;
            return *this;
        }

        inline ffw::Color  operator *  (const float& val) const {
            return Color(r * val, g * val, b * val, a * val);
        }

        inline ffw::Color& operator *= (const float& val) {
            r *= val;
            g *= val;
            b *= val;
            a *= val;
            return *this;
        }
        inline bool operator != (const Color& vec) const {
            return !(*this == vec);
        }
        inline bool operator == (const Color& vec) const {
            if (fabs(r - vec.r) > std::numeric_limits<float>::epsilon())return false;
            if (fabs(g - vec.g) > std::numeric_limits<float>::epsilon())return false;
            if (fabs(b - vec.b) > std::numeric_limits<float>::epsilon())return false;
            if (fabs(a - vec.a) > std::numeric_limits<float>::epsilon())return false;
            return true;
        }
        inline ffw::Color& clamp() {
            r = std::max(0.0f, std::min(r, 1.0f));
            g = std::max(0.0f, std::min(r, 1.0f));
            b = std::max(0.0f, std::min(r, 1.0f));
            a = std::max(0.0f, std::min(r, 1.0f));
            return *this;
        }
        inline ffw::Color& normalize() {
            float l = sqrtf(r*r + g*g + b*b);
            if (l > 0) {
                r = r / l;
                g = g / l;
                b = b / l;
                if (a > 1.0f)a = 1.0f;
                if (a < 0.0f)a = 0.0f;
            }
            return *this;
        }
        inline ffw::Color& scale(const float val) {
            r = r*val;
            g = g*val;
            b = b*val;
            a = a*val;
            return *this;
        }
        inline double length() const {
            return sqrt(static_cast<double>(r*r + g*g + b*b + a*a));
        }
        inline float lengthf() const {
            return sqrtf(static_cast<float>(r*r + g*g + b*b + a*a));
        }
        inline float lengthSqrd() const {
            return (r*r + g*g + b*b + a*a);
        }
        inline Color inverted() const {
            return Color(1.0f - r, 1.0f - g, 1.0f - b, a);
        }
    };
    inline Color rgb(unsigned long hex) {
        return Color(
            ((hex & 0xFF0000) >> 16) / 255.0f,
            ((hex & 0x00FF00) >> 8) / 255.0f,
            (hex & 0x0000FF) / 255.0f,
            1.0f
        );
    }
    inline Color rgb(unsigned char r, unsigned char g, unsigned char b) {
        return Color(
            r / 255.0f,
            g / 255.0f,
            b / 255.0f,
            1.0f
        );
    }
    inline Color rgba(unsigned long hex) {
        return Color(
            ((hex & 0xFF000000) >> 24) / 255.0f,
            ((hex & 0x00FF0000) >> 16) / 255.0f,
            ((hex & 0x0000FF00) >> 8) / 255.0f,
            (hex & 0x000000FF) / 255.0f
        );
    }
    inline Color rgba(unsigned char r, unsigned char g, unsigned char b, unsigned char a) {
        return Color(
            r / 255.0f,
            g / 255.0f,
            b / 255.0f,
            a / 255.0f
        );
    }
    inline Color hsl(const float h, const float s, const float l, const float a = 1.0f) {
        // Converted from JavaScript to C++ from https://gist.github.com/mjackson/5311256
        if (s <= 0.0f) return Color(l, l, l, 1.0f);
        static const auto hue2rgb = [](float p, float q, float t) {
            if (t < 0.0f) t += 1;
            if (t > 1.0f) t -= 1;
            if (t < 1.0f / 6.0f) return p + (q - p) * 6.0f * t;
            if (t < 1.0f / 2.0f) return q;
            if (t < 2.0f / 3.0f) return p + (q - p) * (2.0f / 3.0f - t) * 6.0f;
            return p;
        };

        const auto q = l < 0.5f ? l * (1.0f + s) : l + s - l * s;
        const auto p = 2.0f * l - q;

        return Color(
            hue2rgb(p, q, h + 1.0f / 3.0f),
            hue2rgb(p, q, h),
            hue2rgb(p, q, h - 1.0f / 3.0f),
            a
        );
    }
    inline Color hsv(const float h, const float s, const float v, const float a = 1.0f) {
        // Converted from JavaScript to C++ from https://gist.github.com/mjackson/5311256
        const auto i = int(h * 6.0f);
        const auto f = h * 6.0f - i;
        const auto p = v * (1.0f - s);
        const auto q = v * (1.0f - f * s);
        const auto t = v * (1.0f - (1.0f - f) * s);
        switch (i % 6) {
            case 0: return Color(v, t, p, a);
            case 1: return Color(q, v, p, a);
            case 2: return Color(p, v, t, a);
            case 3: return Color(p, q, v, a);
            case 4: return Color(t, p, v, a);
            case 5: return Color(v, p, q, a);
            default: return Color(0.0f, 0.0f, 0.0f, 1.0f);
        }
    }
    inline ffw::Color normalize(const Color& col) {
        auto copy = col;
        copy.normalize();
        return copy;
    }
    inline ffw::Color clamp(const ffw::Color& color) {
        return ffw::Color(color).clamp();
    }
    inline std::ostream& operator << (std::ostream& os, const ffw::Color& color) {
        os << color.r << ", " << color.g << ", " << color.b << ", " << color.a;
        return os;
    }
};
#endif