color.h File Reference
Go to the documentation of this file.
Source: include/ffw/graphics/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