1#ifndef NEFORCE_CORE_UTILITY_COLOR_HPP__
2#define NEFORCE_CORE_UTILITY_COLOR_HPP__
14NEFORCE_BEGIN_NAMESPACE__
176 static constexpr int clamp(
const int value)
noexcept {
191 static constexpr double clamp_double(
const double value)
noexcept {
208 static constexpr int lerp_component(
const int from,
const int to,
const double t)
noexcept {
209 const double result = from + (to - from) * clamp_double(t);
210 return static_cast<int>(_NEFORCE
round(result));
213 static constexpr int find_closest(
const int value)
noexcept {
214 constexpr int levels[6] = {0, 95, 135, 175, 215, 255};
217 int min_diff = 255 * 255;
218 for (
int i = 0; i < 6; ++i) {
219 const int diff = value - levels[i];
220 const int dist = diff * diff;
221 if (dist < min_diff) {
233 constexpr color() noexcept = default;
235 constexpr
color(const
color& other) noexcept = default;
236 constexpr
color& operator=(const
color& other) noexcept = default;
252 constexpr color(
const int gray,
const int alpha) noexcept :
294 NEFORCE_CONSTEXPR20
explicit color(
const string& str) { *
this =
parse(str.
view()); }
335 NEFORCE_CONSTEXPR20
~color() =
default;
341 NEFORCE_NODISCARD
constexpr int R() const noexcept {
return r; }
347 NEFORCE_NODISCARD
constexpr int G() const noexcept {
return g; }
353 NEFORCE_NODISCARD
constexpr int B() const noexcept {
return b; }
359 NEFORCE_NODISCARD
constexpr int A() const noexcept {
return a; }
365 constexpr void setR(
const int red)
noexcept { r = clamp(
red); }
383 constexpr void setA(
const int alpha)
noexcept { a = clamp(alpha); }
431 NEFORCE_NODISCARD
constexpr bool is_transparent() const noexcept {
return a == 0; }
437 NEFORCE_NODISCARD
constexpr bool is_opaque() const noexcept {
return a == 255; }
443 NEFORCE_NODISCARD
constexpr double opacity() const noexcept {
return a / 255.0; }
465 return {lerp_component(from.r, to.r, t), lerp_component(from.g, to.g, t), lerp_component(from.b, to.b, t),
466 lerp_component(from.a, to.a, t)};
475 return {r + other.r, g + other.g, b + other.b, a + other.a};
484 return {r - other.r, g - other.g, b - other.b, a - other.a};
493 return {
static_cast<int>(_NEFORCE
round(
static_cast<double>(r) * scalar)),
494 static_cast<int>(_NEFORCE
round(
static_cast<double>(g) * scalar)),
495 static_cast<int>(_NEFORCE
round(
static_cast<double>(b) * scalar)),
496 static_cast<int>(_NEFORCE
round(
static_cast<double>(a) * scalar))};
505 return {r * scalar, g * scalar, b * scalar, a * scalar};
514 r = clamp(r + other.r);
515 g = clamp(g + other.g);
516 b = clamp(b + other.b);
517 a = clamp(a + other.a);
527 r = clamp(r - other.r);
528 g = clamp(g - other.g);
529 b = clamp(b - other.b);
530 a = clamp(a - other.a);
540 r = clamp(
static_cast<int>(_NEFORCE
round(r * scalar)));
541 g = clamp(
static_cast<int>(_NEFORCE
round(g * scalar)));
542 b = clamp(
static_cast<int>(_NEFORCE
round(b * scalar)));
543 a = clamp(
static_cast<int>(_NEFORCE
round(a * scalar)));
552 NEFORCE_NODISCARD
constexpr bool equal_to(
const color& other)
const noexcept {
553 return r == other.r && g == other.g && b == other.b && a == other.a;
590 const decimal_t dst_a = background.a / 255.0;
594 const decimal_t out_a = src_a + dst_a * inv_src_a;
602 const int newR =
static_cast<int>(_NEFORCE
round((r * src_a + background.r * dst_a * inv_src_a) * inv_out_a));
603 const int newG =
static_cast<int>(_NEFORCE
round((g * src_a + background.g * dst_a * inv_src_a) * inv_out_a));
604 const int newB =
static_cast<int>(_NEFORCE
round((b * src_a + background.b * dst_a * inv_src_a) * inv_out_a));
605 const int newA =
static_cast<int>(_NEFORCE
round(out_a * 255.0));
607 return {newR, newG, newB, newA};
614 NEFORCE_NODISCARD
constexpr double gray_value() const noexcept {
return 0.299 * r + 0.587 * g + 0.114 * b; }
620 NEFORCE_NODISCARD NEFORCE_CONSTEXPR20
string to_string()
const {
621 return _NEFORCE
format(
"{:02X}{:02X}{:02X}{:02X}", r, g, b, a);
632 if (clean_hex[0] ==
'#') {
633 clean_hex = clean_hex.
tail(1);
636 if (clean_hex.
length() == 6) {
640 return {
static_cast<int>(r),
static_cast<int>(g),
static_cast<int>(b)};
641 }
else if (clean_hex.
length() == 8) {
646 return {
static_cast<int>(r),
static_cast<int>(g),
static_cast<int>(b),
static_cast<int>(a)};
661 if (r == 0 && g == 0 && b == 0) {
664 if (r == 255 && g == 255 && b == 255) {
668 if (r == g && g == b) {
675 const int gray_index = (r - 8) / 10;
676 return 232 + (gray_index > 23 ? 23 : gray_index);
679 const int r_idx = find_closest(r);
680 const int g_idx = find_closest(g);
681 const int b_idx = find_closest(b);
684 return 16 + 36 * r_idx + 6 * g_idx + b_idx;
692 NEFORCE_NODISCARD
constexpr int to_ansi_basic(
const bool is_background =
false) const noexcept {
693 const int base = is_background ? 40 : 30;
695 if (r > g && r > b) {
696 if (g > 128 && b > 128) {
700 }
else if (g > r && g > b) {
701 if (r > 128 && b > 128) {
705 }
else if (b > r && b > g) {
706 if (r > 128 && g > 128) {
710 }
else if (r == g && g == b) {
718 }
else if (r == g && r > b) {
720 }
else if (r == b && r > g) {
722 }
else if (g == b && g > r) {
760 return {
static_cast<int>(_NEFORCE
round(r * alpha)),
static_cast<int>(_NEFORCE
round(g * alpha)),
761 static_cast<int>(_NEFORCE
round(b * alpha)), a};
774 return {
static_cast<int>(_NEFORCE
round(r * inv_alpha)),
static_cast<int>(_NEFORCE
round(g * inv_alpha)),
775 static_cast<int>(_NEFORCE
round(b * inv_alpha)), a};
794 NEFORCE_NODISCARD
constexpr size_t to_hash() const noexcept {
796 return hasher(r) ^ hasher(g) ^ hasher(b) ^ hasher(a);
805 other = _NEFORCE
move(*
this);
806 *
this = _NEFORCE
move(tmp);
810 static constexpr color black() noexcept {
return {0, 0, 0, 255}; }
813 static constexpr color white() noexcept {
return {255, 255, 255, 255}; }
816 static constexpr color gray() noexcept {
return {128, 128, 128, 255}; }
819 static constexpr color red() noexcept {
return {255, 0, 0, 255}; }
822 static constexpr color green() noexcept {
return {0, 255, 0, 255}; }
825 static constexpr color blue() noexcept {
return {0, 0, 255, 255}; }
828 static constexpr color yellow() noexcept {
return {255, 255, 0, 255}; }
831 static constexpr color magenta() noexcept {
return {255, 0, 255, 255}; }
834 static constexpr color cyan() noexcept {
return {0, 255, 255, 255}; }
858NEFORCE_END_NAMESPACE__
constexpr size_type length() const noexcept
获取字符串长度
constexpr basic_string_view tail(const size_type off=0) const
获取尾部子串
constexpr basic_string_view substr(const size_type off=0, const size_type count=npos) const
获取子视图
constexpr view_type view() const noexcept
获取字符串视图
constexpr integer32 to_integer32(const bool use_256_color=true) const noexcept
转换为整数表示
constexpr color(const string &str)
从字符串对象构造
constexpr void setG(const int green) noexcept
设置绿色分量
static constexpr color lerp(const color &from, const color &to, double t) noexcept
线性插值两个颜色
constexpr void set_gray(const int gray) noexcept
设置灰度值
constexpr color(color &&other) noexcept
移动构造函数
constexpr color(const int red, const int green, const int blue, const int alpha) noexcept
从RGBA分量构造
constexpr void set_opacity(double opacity) noexcept
设置不透明度
constexpr void set_gray(const int gray, const int alpha) noexcept
设置灰度值和透明度
constexpr color & operator+=(const color &other) noexcept
颜色加等赋值
constexpr double gray_value() const noexcept
计算灰度值
static constexpr color parse(const string_view hex)
从十六进制字符串解析颜色
constexpr color(const int gray, const int alpha) noexcept
从灰度值和透明度构造
constexpr color from_premultiplied() const noexcept
从预乘 Alpha 转换回直通 Alpha(Straight Alpha)
constexpr void set_color(const int red, const int green, const int blue) noexcept
设置RGB颜色
constexpr int A() const noexcept
获取透明度
constexpr void setR(const int red) noexcept
设置红色分量
constexpr int G() const noexcept
获取绿色分量
constexpr bool is_opaque() const noexcept
检查是否完全不透明
constexpr color(const int red, const int green, const int blue) noexcept
从RGB分量构造
constexpr color() noexcept=default
默认构造函数,创建黑色(0,0,0,255)
constexpr color operator-(const color &other) const noexcept
颜色减法
static constexpr color blue() noexcept
蓝色
constexpr void swap(color &other) noexcept
交换两个颜色对象
constexpr int to_ansi_basic(const bool is_background=false) const noexcept
转换为基本ANSI颜色代码
static constexpr color transparent() noexcept
完全透明
constexpr color(const string_view str)
从十六进制字符串构造
constexpr void setB(const int blue) noexcept
设置蓝色分量
constexpr double opacity() const noexcept
获取不透明度(0.0-1.0)
constexpr size_t to_hash() const noexcept
计算哈希值
constexpr color(const char *str)
从C风格字符串构造
constexpr int B() const noexcept
获取蓝色分量
constexpr color & operator*=(const double scalar) noexcept
颜色乘等赋值
static constexpr color red() noexcept
红色
constexpr color & operator-=(const color &other) noexcept
颜色减等赋值
static constexpr color black() noexcept
黑色
static constexpr color green() noexcept
绿色
constexpr color operator*(const double scalar) const noexcept
颜色乘以标量
constexpr bool is_transparent() const noexcept
检查是否完全透明
constexpr color operator*(const int scalar) const noexcept
颜色乘以整数标量
constexpr bool less_than(const color &other) const noexcept
小于比较
static constexpr color cyan() noexcept
青色
constexpr int to_ansi_256() const noexcept
转换为256色ANSI颜色索引
static constexpr color white() noexcept
白色
constexpr integer32 to_ansi_foreground(const bool use_256_color=true) const noexcept
转换为ANSI前景色代码
constexpr color operator+(const color &other) const noexcept
颜色加法
constexpr void set_color(const int red, const int green, const int blue, const int alpha) noexcept
设置RGBA颜色
constexpr integer32 to_ansi_background(const bool use_256_color=true) const noexcept
转换为ANSI背景色代码
static constexpr color yellow() noexcept
黄色
static constexpr color gray() noexcept
灰色
constexpr color & operator=(color &&other) noexcept
移动赋值运算符
constexpr string to_string() const
转换为十六进制字符串
constexpr color blend(const color &background) const noexcept
将当前颜色与背景色混合
constexpr color to_premultiplied() const noexcept
转换为标准预乘 Alpha 表示
constexpr int R() const noexcept
获取红色分量
static constexpr color magenta() noexcept
品红
constexpr void setA(const int alpha) noexcept
设置透明度
constexpr bool equal_to(const color &other) const noexcept
相等比较
constexpr T * addressof(T &x) noexcept
获取对象的地址
constexpr color operator*(const double scalar, const color &color) noexcept
标量乘以颜色
constexpr const T & max(const T &a, const T &b, Compare comp) noexcept(noexcept(comp(a, b)))
返回两个值中的较大者
constexpr const T & min(const T &a, const T &b, Compare comp) noexcept(noexcept(comp(b, a)))
返回两个值中的较小者
long double decimal_t
扩展精度浮点数类型
long long int64_t
64位有符号整数类型
NEFORCE_NORETURN void unreachable() noexcept
标记不可达代码路径
constexpr decimal_t round(const decimal_t x) noexcept
四舍五入
constexpr Iterator2 move(Iterator1 first, Iterator1 last, Iterator2 result) noexcept(noexcept(inner::__move_aux(first, last, result)))
移动范围元素
basic_string_view< char > string_view
字符字符串视图
static constexpr hexadecimal parse(const string_view str)
从字符串解析十六进制值
constexpr package_type value() const noexcept
获取数值