17#define FTXUI_NOINLINE __declspec(noinline)
19#define FTXUI_NOINLINE __attribute__((noinline))
24const std::array<const char*, 32> palette16code = {
43void AppendNumber(std::string& out, uint8_t n) {
45 out +=
static_cast<char>(
'0' + n / 100);
47 out +=
static_cast<char>(
'0' + n / 10);
49 out +=
static_cast<char>(
'0' + n);
51 out +=
static_cast<char>(
'0' + n / 10);
53 out +=
static_cast<char>(
'0' + n);
55 out +=
static_cast<char>(
'0' + n);
61uint8_t ClosestPalette256(
int r,
int g,
int b) {
63 auto cube_index = [](
int v) {
64 return v < 48 ? 0 : v < 116 ? 1 : (v - 36) / 40;
66 auto cube_level = [](
int i) {
return i == 0 ? 0 : 55 + 40 * i; };
67 const int ri = cube_index(r);
68 const int gi = cube_index(g);
69 const int bi = cube_index(b);
70 const int cr = cube_level(ri) - r;
71 const int cg = cube_level(gi) - g;
72 const int cb = cube_level(bi) - b;
73 const int cube_distance = cr * cr + cg * cg + cb * cb;
77 const int gray_index = std::clamp((r + g + b - 10) / 30, 0, 23);
78 const int gray_level = 8 + 10 * gray_index;
79 const int dr = gray_level - r;
80 const int dg = gray_level - g;
81 const int db = gray_level - b;
82 const int gray_distance = dr * dr + dg * dg + db * db;
84 return gray_distance < cube_distance ? 232 + gray_index
85 : 16 + 36 * ri + 6 * gi + bi;
92 bool is_background_color,
99 out.append(is_background_color ?
"49" :
"39", 2);
102 const uint8_t index = is_rgb ? ClosestPalette256(r, g, b) : r;
104 out.append(is_background_color ?
"48;5;" :
"38;5;", 5);
105 AppendNumber(out, index);
108 const uint8_t index_16 =
GetColorInfo(Color::Palette256(index)).index_16;
109 out.append(palette16code[2 * index_16 + (is_background_color ? 1 : 0)]);
114bool Color::operator==(
const Color& rhs)
const {
115 return red_ == rhs.red_ && green_ == rhs.green_ && blue_ == rhs.blue_ &&
119bool Color::operator!=(
const Color& rhs)
const {
120 return !operator==(rhs);
123std::string Color::Print(
bool is_background_color)
const {
125 PrintTo(out, is_background_color);
132void Color::PrintTo(std::string& out,
bool is_background_color)
const {
133 PrintTo(out, is_background_color, Terminal::ColorSupport());
141void Color::PrintTo(std::string& out,
142 bool is_background_color,
146 if (
static_cast<uint8_t
>(type_) >
static_cast<uint8_t
>(support)) {
147 PrintDegraded(out, is_background_color, type_ == ColorType::TrueColor, red_,
148 green_, blue_, support);
153 case ColorType::Palette1:
154 out.append(is_background_color ?
"49" :
"39", 2);
156 case ColorType::Palette16:
157 out.append(palette16code[2 * red_ + (is_background_color ? 1 : 0)]);
159 case ColorType::Palette256:
160 out.append(is_background_color ?
"48;5;" :
"38;5;", 5);
161 AppendNumber(out, red_);
163 case ColorType::TrueColor:
164 out.append(is_background_color ?
"48;2;" :
"38;2;", 5);
165 AppendNumber(out, red_);
167 AppendNumber(out, green_);
169 AppendNumber(out, blue_);
175Color::Color() =
default;
178Color::Color(Palette1 ) :
Color() {}
181Color::Color(Palette16 index)
182 : type_(ColorType::Palette16), red_(index), alpha_(255) {}
185Color::Color(Palette256 index)
186 : type_(ColorType::Palette256), red_(index), alpha_(255) {}
195Color::Color(uint8_t red, uint8_t green, uint8_t blue, uint8_t alpha)
196 : type_(ColorType::TrueColor),
209Color Color::RGB(uint8_t red, uint8_t green, uint8_t blue) {
210 return RGBA(red, green, blue, 255);
221Color Color::RGBA(uint8_t red, uint8_t green, uint8_t blue, uint8_t alpha) {
222 return {red, green, blue, alpha};
233Color Color::HSVA(uint8_t h, uint8_t s, uint8_t v, uint8_t alpha) {
234 uint8_t region = h / 43;
235 uint8_t remainder = (h - (region * 43)) * 6;
236 uint8_t p = (v * (255 - s)) >> 8;
237 uint8_t q = (v * (255 - ((s * remainder) >> 8))) >> 8;
238 uint8_t t = (v * (255 - ((s * (255 - remainder)) >> 8))) >> 8;
242 case 0:
return Color(v,t,p, alpha);
243 case 1:
return Color(q,v,p, alpha);
244 case 2:
return Color(p,v,t, alpha);
245 case 3:
return Color(p,q,v, alpha);
246 case 4:
return Color(t,p,v, alpha);
247 case 5:
return Color(v,p,q, alpha);
250 return {0, 0, 0, alpha};
260Color Color::HSV(uint8_t h, uint8_t s, uint8_t v) {
261 return HSVA(h, s, v, 255);
265Color Color::Interpolate(
float t,
const Color& a,
const Color& b) {
266 if (a.type_ == ColorType::Palette1 ||
267 b.type_ == ColorType::Palette1) {
277 auto interp = [t](uint8_t a_u, uint8_t b_u) {
278 constexpr float gamma = 2.2F;
279 const float a_f = std::pow(a_u, gamma);
280 const float b_f = std::pow(b_u, gamma);
281 const float c_f = a_f * (1.0F - t) +
283 return static_cast<uint8_t
>(std::pow(c_f, 1.F / gamma));
285 return Color::RGB(interp(a.GetRed(), b.GetRed()),
286 interp(a.GetGreen(), b.GetGreen()),
287 interp(a.GetBlue(), b.GetBlue()));
293uint8_t Color::GetRed()
const {
295 case ColorType::Palette1:
297 case ColorType::Palette16:
298 case ColorType::Palette256:
299 return GetColorInfo(Palette256(red_)).red;
300 case ColorType::TrueColor:
309uint8_t Color::GetGreen()
const {
311 case ColorType::Palette1:
313 case ColorType::Palette16:
314 case ColorType::Palette256:
315 return GetColorInfo(Palette256(red_)).green;
316 case ColorType::TrueColor:
325uint8_t Color::GetBlue()
const {
327 case ColorType::Palette1:
329 case ColorType::Palette16:
330 case ColorType::Palette256:
331 return GetColorInfo(Palette256(red_)).blue;
332 case ColorType::TrueColor:
339uint8_t Color::GetAlpha()
const {
345Color Color::Blend(
const Color& lhs,
const Color& rhs) {
346 Color out = Interpolate(
float(rhs.alpha_) / 255.F, lhs, rhs);
347 out.alpha_ = lhs.alpha_ + rhs.alpha_ - lhs.alpha_ * rhs.alpha_ / 255;
353Color
operator""_rgb(
unsigned long long int combined) {
355 auto const red =
static_cast<uint8_t
>(combined >> 16U);
356 auto const green =
static_cast<uint8_t
>(combined >> 8U);
357 auto const blue =
static_cast<uint8_t
>(combined);
358 return {red, green, blue};
Color
Color is an enumeration that represents the color support of the terminal.
The FTXUI ftxui:: namespace.
ColorInfo GetColorInfo(Color::Palette256 index)
Color
Build a transparent color.
The FTXUI ftxui::literals:: namespace.