koutil
Loading...
Searching...
No Matches
color.h
Go to the documentation of this file.
1#ifndef KOUTIL_TERM_COLOR_H
2#define KOUTIL_TERM_COLOR_H
3
4#include <array>
5#include <cassert>
6#include <cmath>
7#include <cstdint>
8#include <string_view>
9#include <type_traits>
10
11namespace koutil::term {
12
13struct ColorBG;
14struct ColorFG;
15
23struct Color {
24public:
25 using channel_t = std::uint8_t;
26
27 enum class Tag : std::uint8_t {
28 RGB,
29 ID,
30 };
31
35 const Tag tag;
36
37public:
38 constexpr Color()
39 : red()
40 , green()
41 , blue()
42 , tag(Tag::RGB) { }
43
54 : red(r)
55 , green(g)
56 , blue(b)
57 , tag(Tag::RGB) { }
58
66 constexpr Color(std::uint8_t id)
67 : red(id)
68 , green()
69 , blue()
70 , tag(Tag::ID) { }
71
80 static constexpr Color from_rgb(channel_t red, channel_t green, channel_t blue) { return { red, green, blue }; }
81
88 static constexpr Color from_id(channel_t id) { return { id }; }
89
98 static constexpr Color from_hsv(std::uint16_t h, float s, float v);
99
106 static consteval Color from_hex(std::string_view hex) {
107 if (!hex.starts_with('#')) {
108 assert(false);
109 }
110
111 if (hex.size() - 1 == 3) {
112 return {
113 static_cast<channel_t>(extract_value(hex[1]) | (extract_value(hex[1]) << 4)),
114 static_cast<channel_t>(extract_value(hex[2]) | (extract_value(hex[2]) << 4)),
115 static_cast<channel_t>(extract_value(hex[3]) | (extract_value(hex[3]) << 4)),
116 };
117 } else if (hex.size() - 1 == 6) {
118 return {
119 static_cast<channel_t>(extract_value(hex[2]) | (extract_value(hex[1]) << 4)),
120 static_cast<channel_t>(extract_value(hex[4]) | (extract_value(hex[3]) << 4)),
121 static_cast<channel_t>(extract_value(hex[6]) | (extract_value(hex[5]) << 4)),
122 };
123 } else {
124 assert(false);
125 }
126 }
127
133 [[nodiscard]] constexpr std::array<channel_t, 3> get_channels() const {
134 assert(tag == Tag::RGB);
135 return { red, green, blue };
136 }
137
143 [[nodiscard]] constexpr channel_t id() const { return red; }
144
150 [[nodiscard]] constexpr ColorBG as_bg() const;
151
157 [[nodiscard]] constexpr ColorFG as_fg() const;
158
159 constexpr bool operator==(Color other) const {
160 return red == other.red && green == other.green && blue == other.blue && tag == other.tag;
161 }
162
163private:
170 static consteval std::uint8_t extract_value(char val) {
171 if ('a' <= val && val <= 'f') {
172 return static_cast<std::uint8_t>(10 + val - 'a');
173 } else if ('A' <= val && val <= 'F') {
174 return static_cast<std::uint8_t>(10 + val - 'A');
175 } else {
176 return static_cast<std::uint8_t>(val - '0');
177 }
178 }
179
186 static constexpr std::uint8_t convert_val(float val) {
187 if (std::is_constant_evaluated()) {
188 return static_cast<std::uint8_t>(val * 255.0F + 0.5F);
189 } else {
190 return static_cast<std::uint8_t>(std::round(val * 255.0F));
191 }
192 }
193};
194
198struct ColorBG {
199 constexpr ColorBG(Color c)
200 : color(c) { }
201
203};
204
208struct ColorFG {
209 constexpr ColorFG(Color c)
210 : color(c) { }
211
213};
214
215constexpr ColorBG Color::as_bg() const { return { *this }; }
216
217constexpr ColorFG Color::as_fg() const { return { *this }; }
218
219constexpr Color Color::from_hsv(std::uint16_t h, float s, float v) {
220 constexpr std::uint16_t HUE_PART = 360 / 6;
221 constexpr float HUE_PART_FLOAT = 360.0F / 6.0F;
222
223 if (s <= 0.0001F) {
224 channel_t val = convert_val(v);
225 return { val, val, val };
226 }
227
228 h %= 360;
229
230 const auto region = h / HUE_PART;
231 const auto rem = static_cast<float>(h % HUE_PART) / HUE_PART_FLOAT;
232
233 const float p = v * (1.0F - s);
234 const float q = v * (1.0F - (s * rem));
235 const auto t = v * (1.0F - (s * (1.0F - rem)));
236
237 float r = 0.F;
238 float g = 0.F;
239 float b = 0.F;
240
241 switch (region) {
242 case 0:
243 r = v;
244 g = t;
245 b = p;
246 break;
247 case 1:
248 r = q;
249 g = v;
250 b = p;
251 break;
252 case 2:
253 r = p;
254 g = v;
255 b = t;
256 break;
257 case 3:
258 r = p;
259 g = q;
260 b = v;
261 break;
262 case 4:
263 r = t;
264 g = p;
265 b = v;
266 break;
267 case 5:
268 default:
269 r = v;
270 g = p;
271 b = q;
272 break;
273 }
274
275 return { convert_val(r), convert_val(g), convert_val(b) };
276}
277
278}
279
280#endif
Definition color.h:11
Structure representing a background color.
Definition color.h:198
constexpr ColorBG(Color c)
Definition color.h:199
const Color color
Definition color.h:202
Structure representing a foreground color.
Definition color.h:208
const Color color
Definition color.h:212
constexpr ColorFG(Color c)
Definition color.h:209
Structure representing a color.
Definition color.h:23
constexpr channel_t id() const
Gets the ID value of the color.
Definition color.h:143
static constexpr Color from_id(channel_t id)
Creates a Color object from an ID value.
Definition color.h:88
static constexpr std::uint8_t convert_val(float val)
Converts a floating-point value to a channel value.
Definition color.h:186
constexpr Color(std::uint8_t id)
Constructor with an ID value.
Definition color.h:66
constexpr bool operator==(Color other) const
Definition color.h:159
constexpr Color()
Definition color.h:38
Tag
Definition color.h:27
constexpr ColorBG as_bg() const
Converts the color to a ColorBG object.
Definition color.h:215
const channel_t red
Definition color.h:32
constexpr ColorFG as_fg() const
Converts the color to a ColorFG object.
Definition color.h:217
static constexpr Color from_rgb(channel_t red, channel_t green, channel_t blue)
Creates a Color object from RGB values.
Definition color.h:80
const Tag tag
Definition color.h:35
static consteval std::uint8_t extract_value(char val)
Extracts a value from a hexadecimal character.
Definition color.h:170
const channel_t blue
Definition color.h:34
const channel_t green
Definition color.h:33
static consteval Color from_hex(std::string_view hex)
Creates a Color object from a hexadecimal string.
Definition color.h:106
constexpr std::array< channel_t, 3 > get_channels() const
Gets the RGB channel values of the color.
Definition color.h:133
std::uint8_t channel_t
Definition color.h:25
static constexpr Color from_hsv(std::uint16_t h, float s, float v)
Creates a Color object from HSV values.
Definition color.h:219
constexpr Color(channel_t r, channel_t g, channel_t b)
Constructor with RGB values.
Definition color.h:53