17const std::array<const char*, 32> palette16code = {
36void AppendNumber(std::string& out, uint8_t n) {
38 out +=
static_cast<char>(
'0' + n / 100);
40 out +=
static_cast<char>(
'0' + n / 10);
42 out +=
static_cast<char>(
'0' + n);
44 out +=
static_cast<char>(
'0' + n / 10);
46 out +=
static_cast<char>(
'0' + n);
48 out +=
static_cast<char>(
'0' + n);
54bool Color::operator==(
const Color& rhs)
const {
55 return red_ == rhs.red_ && green_ == rhs.green_ && blue_ == rhs.blue_ &&
59bool Color::operator!=(
const Color& rhs)
const {
60 return !operator==(rhs);
63std::string Color::Print(
bool is_background_color)
const {
65 PrintTo(out, is_background_color);
72void Color::PrintTo(std::string& out,
bool is_background_color)
const {
74 case ColorType::Palette1:
75 out.append(is_background_color ?
"49" :
"39", 2);
77 case ColorType::Palette16:
78 out.append(palette16code[2 * red_ + (is_background_color ? 1 : 0)]);
80 case ColorType::Palette256:
81 out.append(is_background_color ?
"48;5;" :
"38;5;", 5);
82 AppendNumber(out, red_);
84 case ColorType::TrueColor:
85 out.append(is_background_color ?
"48;2;" :
"38;2;", 5);
86 AppendNumber(out, red_);
88 AppendNumber(out, green_);
90 AppendNumber(out, blue_);
96Color::Color() =
default;
99Color::Color(Palette1 ) : Color() {}
102Color::Color(Palette16 index)
103 : type_(ColorType::
Palette16), red_(index), alpha_(255) {
104 if (Terminal::ColorSupport() == Terminal::Color::Palette1) {
105 type_ = ColorType::Palette1;
110Color::Color(Palette256 index)
111 : type_(ColorType::
Palette256), red_(index), alpha_(255) {
112 if (Terminal::ColorSupport() >= Terminal::Color::Palette256) {
115 if (Terminal::ColorSupport() == Terminal::Color::Palette1) {
116 type_ = ColorType::Palette1;
119 type_ = ColorType::Palette16;
120 red_ = GetColorInfo(Color::Palette256(red_)).index_16;
130Color::Color(uint8_t red, uint8_t green, uint8_t blue, uint8_t alpha)
136 if (Terminal::ColorSupport() == Terminal::Color::TrueColor) {
139 if (Terminal::ColorSupport() == Terminal::Color::Palette1) {
140 type_ = ColorType::Palette1;
145 const int max_distance = 256 * 256 * 3;
146 int closest = max_distance;
148 const int database_begin = 16;
149 const int database_end = 256;
150 for (
int i = database_begin; i < database_end; ++i) {
151 const ColorInfo color_info = GetColorInfo(Color::Palette256(i));
152 const int dr = color_info.red - red;
153 const int dg = color_info.green - green;
154 const int db = color_info.blue - blue;
155 const int dist = dr * dr + dg * dg + db * db;
156 if (closest > dist) {
162 if (Terminal::ColorSupport() == Terminal::Color::Palette256) {
163 type_ = ColorType::Palette256;
166 type_ = ColorType::Palette16;
167 red_ = GetColorInfo(Color::Palette256(best)).index_16;
178Color Color::RGB(uint8_t red, uint8_t green, uint8_t blue) {
179 return RGBA(red, green, blue, 255);
190Color Color::RGBA(uint8_t red, uint8_t green, uint8_t blue, uint8_t alpha) {
191 return {red, green, blue, alpha};
202Color Color::HSVA(uint8_t h, uint8_t s, uint8_t v, uint8_t alpha) {
203 uint8_t region = h / 43;
204 uint8_t remainder = (h - (region * 43)) * 6;
205 uint8_t p = (v * (255 - s)) >> 8;
206 uint8_t q = (v * (255 - ((s * remainder) >> 8))) >> 8;
207 uint8_t t = (v * (255 - ((s * (255 - remainder)) >> 8))) >> 8;
211 case 0:
return Color(v,t,p, alpha);
212 case 1:
return Color(q,v,p, alpha);
213 case 2:
return Color(p,v,t, alpha);
214 case 3:
return Color(p,q,v, alpha);
215 case 4:
return Color(t,p,v, alpha);
216 case 5:
return Color(v,p,q, alpha);
219 return {0, 0, 0, alpha};
229Color Color::HSV(uint8_t h, uint8_t s, uint8_t v) {
230 return HSVA(h, s, v, 255);
234Color Color::Interpolate(
float t,
const Color& a,
const Color& b) {
235 if (a.type_ == ColorType::Palette1 ||
236 b.type_ == ColorType::Palette1) {
246 auto interp = [t](uint8_t a_u, uint8_t b_u) {
247 constexpr float gamma = 2.2F;
248 const float a_f = std::pow(a_u, gamma);
249 const float b_f = std::pow(b_u, gamma);
250 const float c_f = a_f * (1.0F - t) +
252 return static_cast<uint8_t
>(std::pow(c_f, 1.F / gamma));
254 return Color::RGB(interp(a.GetRed(), b.GetRed()),
255 interp(a.GetGreen(), b.GetGreen()),
256 interp(a.GetBlue(), b.GetBlue()));
262uint8_t Color::GetRed()
const {
264 case ColorType::Palette1:
266 case ColorType::Palette16:
267 case ColorType::Palette256:
269 case ColorType::TrueColor:
278uint8_t Color::GetGreen()
const {
280 case ColorType::Palette1:
282 case ColorType::Palette16:
283 case ColorType::Palette256:
285 case ColorType::TrueColor:
294uint8_t Color::GetBlue()
const {
296 case ColorType::Palette1:
298 case ColorType::Palette16:
299 case ColorType::Palette256:
301 case ColorType::TrueColor:
308uint8_t Color::GetAlpha()
const {
314Color Color::Blend(
const Color& lhs,
const Color& rhs) {
315 Color out = Interpolate(
float(rhs.alpha_) / 255.F, lhs, rhs);
316 out.alpha_ = lhs.alpha_ + rhs.alpha_ - lhs.alpha_ * rhs.alpha_ / 255;
322Color
operator""_rgb(
unsigned long long int combined) {
324 auto const red =
static_cast<uint8_t
>(combined >> 16U);
325 auto const green =
static_cast<uint8_t
>(combined >> 8U);
326 auto const blue =
static_cast<uint8_t
>(combined);
327 return {red, green, blue};
The FTXUI ftxui:: namespace.
The FTXUI ftxui::literals:: namespace.