MSTL 1.4.0
A Modern C++ Library with extended functionality, web components, and utility libraries
载入中...
搜索中...
未找到
color.hpp
1#ifndef MSTL_CORE_UTILITY_COLOR_HPP__
2#define MSTL_CORE_UTILITY_COLOR_HPP__
3#include "hexadecimal.hpp"
4#include "packages.hpp"
6
7class color : public iobject<color>, public icommon<color> {
8private:
9 int r = 0, g = 0, b = 0, a = 255;
10
11 static constexpr int clamp(const int value) noexcept {
12 if (value < 0) return 0;
13 if (value > 255) return 255;
14 return value;
15 }
16
17 static constexpr double clamp_double(const double value) noexcept {
18 if (value < 0.0) return 0.0;
19 if (value > 1.0) return 1.0;
20 return value;
21 }
22
23 static constexpr int lerp_component(const int from, const int to, const double t) noexcept {
24 const double result = from + (to - from) * clamp_double(t);
25 return static_cast<int>(_MSTL round(result));
26 }
27
28public:
29 constexpr color() noexcept = default;
30
31 explicit constexpr color(const int gray) noexcept
32 : r(clamp(gray)), g(clamp(gray)), b(clamp(gray)) {}
33
34 constexpr color(const int gray, const int alpha) noexcept
35 : r(clamp(gray)), g(clamp(gray)), b(clamp(gray)), a(clamp(alpha)) {}
36
37 constexpr color(const int red, const int green, const int blue) noexcept
38 : r(clamp(red)), g(clamp(green)), b(clamp(blue)) {}
39
40 constexpr color(const int red, const int green, const int blue, const int alpha) noexcept
41 : r(clamp(red)), g(clamp(green)), b(clamp(blue)), a(clamp(alpha)) {}
42
43 MSTL_CONSTEXPR20 explicit color(const string_view str) { try_parse(str); }
44 MSTL_CONSTEXPR20 explicit color(const string& str) { try_parse(str.view()); }
45 MSTL_CONSTEXPR20 explicit color(const char* str) { try_parse(str); }
46
47 constexpr color(const color& other) noexcept = default;
48 constexpr color& operator =(const color& other) noexcept = default;
49 constexpr color(color&& other) noexcept : r(other.r), g(other.g), b(other.b), a(other.a) {
50 other.r = 0;
51 other.g = 0;
52 other.b = 0;
53 other.a = 255;
54 }
55 constexpr color& operator =(color&& other) noexcept {
56 if (_MSTL addressof(other) == this) return *this;
57 this->swap(other);
58 return *this;
59 }
60
61 MSTL_CONSTEXPR20 ~color() = default;
62
63 constexpr int R() const noexcept { return r; }
64 constexpr int G() const noexcept { return g; }
65 constexpr int B() const noexcept { return b; }
66 constexpr int A() const noexcept { return a; }
67
68 constexpr void setR(const int red) noexcept { r = clamp(red); }
69 constexpr void setG(const int green) noexcept { g = clamp(green); }
70 constexpr void setB(const int blue) noexcept { b = clamp(blue); }
71 constexpr void setA(const int alpha) noexcept { a = clamp(alpha); }
72
73 constexpr void set_color(const int red, const int green, const int blue) noexcept {
74 r = clamp(red);
75 g = clamp(green);
76 b = clamp(blue);
77 }
78
79 constexpr void set_color(const int red, const int green, const int blue, const int alpha) noexcept {
80 r = clamp(red);
81 g = clamp(green);
82 b = clamp(blue);
83 a = clamp(alpha);
84 }
85
86 constexpr void set_gray(const int gray) noexcept {
87 r = g = b = clamp(gray);
88 }
89
90 constexpr void set_gray(const int gray, const int alpha) noexcept {
91 set_gray(gray);
92 a = clamp(alpha);
93 }
94
95 constexpr bool is_transparent() const noexcept { return a == 0; }
96 constexpr bool is_opaque() const noexcept { return a == 255; }
97
98 constexpr double opacity() const noexcept { return a / 255.0; }
99
100 constexpr void set_opacity(double opacity) noexcept {
101 if (opacity < 0.0) opacity = 0.0;
102 if (opacity > 1.0) opacity = 1.0;
103 a = static_cast<int>(_MSTL round(opacity * 255));
104 }
105
106 static constexpr color lerp(const color& from, const color& to, double t) noexcept {
107 t = clamp_double(t);
108 return color(
109 lerp_component(from.r, to.r, t),
110 lerp_component(from.g, to.g, t),
111 lerp_component(from.b, to.b, t),
112 lerp_component(from.a, to.a, t)
113 );
114 }
115
116 constexpr color operator +(const color& other) const noexcept {
117 return color(r + other.r, g + other.g, b + other.b, a + other.a);
118 }
119
120 constexpr color operator -(const color& other) const noexcept {
121 return color(r - other.r, g - other.g, b - other.b, a - other.a);
122 }
123
124 constexpr color operator *(const double scalar) const noexcept {
125 return color(
126 static_cast<int>(_MSTL round(r * scalar)),
127 static_cast<int>(_MSTL round(g * scalar)),
128 static_cast<int>(_MSTL round(b * scalar)),
129 static_cast<int>(_MSTL round(a * scalar))
130 );
131 }
132
133 constexpr color operator *(const int scalar) const noexcept {
134 return {r * scalar, g * scalar, b * scalar, a * scalar};
135 }
136
137 constexpr color& operator +=(const color& other) noexcept {
138 r = clamp(r + other.r);
139 g = clamp(g + other.g);
140 b = clamp(b + other.b);
141 a = clamp(a + other.a);
142 return *this;
143 }
144
145 constexpr color& operator -=(const color& other) noexcept {
146 r = clamp(r - other.r);
147 g = clamp(g - other.g);
148 b = clamp(b - other.b);
149 a = clamp(a - other.a);
150 return *this;
151 }
152
153 constexpr color& operator *=(const double scalar) noexcept {
154 r = clamp(static_cast<int>(_MSTL round(r * scalar)));
155 g = clamp(static_cast<int>(_MSTL round(g * scalar)));
156 b = clamp(static_cast<int>(_MSTL round(b * scalar)));
157 a = clamp(static_cast<int>(_MSTL round(a * scalar)));
158 return *this;
159 }
160
161 constexpr bool operator ==(const color& other) const noexcept {
162 return r == other.r && g == other.g && b == other.b && a == other.a;
163 }
164
165 constexpr bool operator <(const color& other) const noexcept {
166 if (r != other.r) return r < other.r;
167 if (g != other.g) return g < other.g;
168 if (b != other.b) return b < other.b;
169 return a < other.a;
170 }
171
172 MSTL_NODISCARD constexpr color blend(const color& background) const noexcept {
173 if (a == 255) return *this;
174 if (a == 0) return background;
175
176 const double alpha = a / 255.0;
177 const double inv_alpha = 1.0 - alpha;
178
179 const int newR = static_cast<int>(_MSTL round(r * alpha + background.r * inv_alpha));
180 const int newG = static_cast<int>(_MSTL round(g * alpha + background.g * inv_alpha));
181 const int newB = static_cast<int>(_MSTL round(b * alpha + background.b * inv_alpha));
182 return color(newR, newG, newB, 255);
183 }
184
185 MSTL_NODISCARD constexpr color premultiply_alpha() const noexcept {
186 const double alpha = a / 255.0;
187 return color(
188 static_cast<int>(_MSTL round(r * alpha)),
189 static_cast<int>(_MSTL round(g * alpha)),
190 static_cast<int>(_MSTL round(b * alpha)),
191 a
192 );
193 }
194
195 MSTL_NODISCARD constexpr double gray_value() const noexcept {
196 return 0.299 * r + 0.587 * g + 0.114 * b;
197 }
198
199 MSTL_NODISCARD MSTL_CONSTEXPR20 string to_string() const {
200 return _MSTL format("{02X}{02X}{02X}{02X}", r, g, b, a);
201 }
202
203 static MSTL_CONSTEXPR20 color parse(const string_view hex) {
204 string_view clean_hex = hex;
205 if (clean_hex[0] == '#') clean_hex = clean_hex.substr(1);
206
207 if (clean_hex.length() == 6) {
208 const int r = hexadecimal::parse(clean_hex.substr(0, 2)).value();
209 const int g = hexadecimal::parse(clean_hex.substr(2, 2)).value();
210 const int b = hexadecimal::parse(clean_hex.substr(4, 2)).value();
211 return {r, g, b};
212 } else if (clean_hex.length() == 8) {
213 const int r = hexadecimal::parse(clean_hex.substr(0, 2)).value();
214 const int g = hexadecimal::parse(clean_hex.substr(2, 2)).value();
215 const int b = hexadecimal::parse(clean_hex.substr(4, 2)).value();
216 const int a = hexadecimal::parse(clean_hex.substr(6, 2)).value();
217 return {r, g, b, a};
218 } else {
219 throw_exception(value_exception("Invalid hex string"));
220 }
221 return {};
222 }
223
224 MSTL_NODISCARD constexpr int to_ansi_256() const noexcept {
225 if (r < 8 && g < 8 && b < 8) return 16;
226 if (r > 248 && g > 248 && b > 248) return 231;
227
228 if (r == g && g == b) {
229 const int gray_index = static_cast<int>((r - 8) / 247.0 * 24.0 + 0.5);
230 return 232 + gray_index;
231 }
232
233 const int r_idx = static_cast<int>((r / 255.0) * 5.0 + 0.5);
234 const int g_idx = static_cast<int>((g / 255.0) * 5.0 + 0.5);
235 const int b_idx = static_cast<int>((b / 255.0) * 5.0 + 0.5);
236
237 return 16 + 36 * r_idx + 6 * g_idx + b_idx;
238 }
239
240 MSTL_NODISCARD constexpr int to_ansi_basic(const bool is_background = false) const noexcept {
241 const int base = is_background ? 40 : 30;
242
243 if (r > g && r > b) {
244 if (g > 128 && b > 128) return base + 7;
245 return base + 1;
246 } else if (g > r && g > b) {
247 if (r > 128 && b > 128) return base + 7;
248 return base + 2;
249 } else if (b > r && b > g) {
250 if (r > 128 && g > 128) return base + 7;
251 return base + 4;
252 } else if (r == g && g == b) {
253 if (r < 64) return base + 0;
254 if (r < 192) return base + 7;
255 return base + 7;
256 } else if (r == g && r > b) {
257 return base + 3;
258 } else if (r == b && r > g) {
259 return base + 5;
260 } else if (g == b && g > r) {
261 return base + 6;
262 }
263
264 return base + 7;
265 }
266
267 MSTL_NODISCARD constexpr integer32 to_ansi_foreground(const bool use_256_color = true) const noexcept {
268 if (use_256_color) {
269 return {38 * 100 + 5 * 10 + to_ansi_256()};
270 }
271 return {to_ansi_basic(false)};
272 }
273
274 MSTL_NODISCARD constexpr integer32 to_ansi_background(const bool use_256_color = true) const noexcept {
275 if (use_256_color) {
276 return {48 * 100 + 5 * 10 + to_ansi_256()};
277 }
278 return {to_ansi_basic(true)};
279 }
280
281 MSTL_NODISCARD constexpr integer32 to_integer32(const bool use_256_color = true) const noexcept {
282 if (use_256_color) {
283 return {to_ansi_256()};
284 }
285 return {to_ansi_basic(false)};
286 }
287
288 MSTL_NODISCARD constexpr size_t to_hash() const noexcept {
289 constexpr hash<int> hasher;
290 return hasher(r) ^ hasher(g) ^ hasher(b) ^ hasher(a);
291 }
292
293 constexpr void swap(color& other) noexcept {
294 color tmp = _MSTL move(other);
295 other = _MSTL move(*this);
296 *this = _MSTL move(tmp);
297 }
298
299 static constexpr color black() noexcept { return color(0, 0, 0, 255); }
300 static constexpr color white() noexcept { return color(255, 255, 255, 255); }
301 static constexpr color red() noexcept { return color(255, 0, 0, 255); }
302 static constexpr color green() noexcept { return color(0, 255, 0, 255); }
303 static constexpr color blue() noexcept { return color(0, 0, 255, 255); }
304 static constexpr color yellow() noexcept { return color(255, 255, 0, 255); }
305 static constexpr color magenta() noexcept { return color(255, 0, 255, 255); }
306 static constexpr color cyan() noexcept { return color(0, 255, 255, 255); }
307 static constexpr color transparent() noexcept { return color(0, 0, 0, 0); }
308};
309
310constexpr color operator *(const double scalar, const color& color) noexcept {
311 return color * scalar;
312}
313constexpr color operator *(const int scalar, const color& color) noexcept {
314 return color * scalar;
315}
316
318#endif // MSTL_CORE_UTILITY_COLOR_HPP__
MSTL_NODISCARD constexpr T * addressof(T &x) noexcept
获取对象的地址
constexpr const T & clamp(const T &value, const T &lower, const T &upper, Compare comp) noexcept(noexcept(comp(value, lower)))
将值限制在指定范围内
constexpr duration< _INNER __common_rep_t< Rep1, Rep2 >, Period > operator*(const duration< Rep1, Period > &value, const Rep2 &scalar)
乘法运算符(持续时间 * 标量)
bool operator==(const function< Res(Args...)> &f, nullptr_t null) noexcept
等于空指针比较
MSTL_CONST_FUNCTION MSTL_CONSTEXPR14 decimal_t round(const decimal_t x) noexcept
四舍五入
#define _MSTL
全局命名空间MSTL前缀
#define MSTL_END_NAMESPACE__
结束全局命名空间MSTL
#define MSTL_BEGIN_NAMESPACE__
开始全局命名空间MSTL
MSTL_NODISCARD constexpr normal_iterator< Iterator > operator+(iter_difference_t< normal_iterator< Iterator > > n, const normal_iterator< Iterator > &iter) noexcept
加法运算符
MSTL_NODISCARD constexpr auto operator-(const normal_iterator< LeftIter > &lhs, const normal_iterator< RightIter > &rhs) noexcept -> decltype(lhs.base() - rhs.base())
减法运算符
MSTL_NODISCARD constexpr bool operator<(const normal_iterator< LeftIter > &lhs, const normal_iterator< RightIter > &rhs) noexcept
小于比较运算符
constexpr Iterator2 move(Iterator1 first, Iterator1 last, Iterator2 result)
移动范围元素
void swap()=delete
删除无参数的swap重载
通用接口,同时具备可比较和可哈希功能