18const std::array<const char*, 32> palette16code = {
37void AppendNumber(std::string& out, uint8_t n) {
39 out +=
static_cast<char>(
'0' + n / 100);
41 out +=
static_cast<char>(
'0' + n / 10);
43 out +=
static_cast<char>(
'0' + n);
45 out +=
static_cast<char>(
'0' + n / 10);
47 out +=
static_cast<char>(
'0' + n);
49 out +=
static_cast<char>(
'0' + n);
55bool Color::operator==(
const Color& rhs)
const {
56 return red_ == rhs.red_ && green_ == rhs.green_ && blue_ == rhs.blue_ &&
60bool Color::operator!=(
const Color& rhs)
const {
61 return !operator==(rhs);
64std::string Color::Print(
bool is_background_color)
const {
66 PrintTo(out, is_background_color);
73void Color::PrintTo(std::string& out,
bool is_background_color)
const {
75 case ColorType::Palette1:
76 out.append(is_background_color ?
"49" :
"39", 2);
78 case ColorType::Palette16:
79 out.append(palette16code[2 * red_ + (is_background_color ? 1 : 0)]);
81 case ColorType::Palette256:
82 out.append(is_background_color ?
"48;5;" :
"38;5;", 5);
83 AppendNumber(out, red_);
85 case ColorType::TrueColor:
86 out.append(is_background_color ?
"48;2;" :
"38;2;", 5);
87 AppendNumber(out, red_);
89 AppendNumber(out, green_);
91 AppendNumber(out, blue_);
97Color::Color() =
default;
100Color::Color(Palette1 ) : Color() {}
103Color::Color(Palette16 index)
104 : type_(ColorType::
Palette16), red_(index), alpha_(255) {
105 if (Terminal::ColorSupport() == Terminal::Color::Palette1) {
106 type_ = ColorType::Palette1;
111Color::Color(Palette256 index)
112 : type_(ColorType::
Palette256), red_(index), alpha_(255) {
113 if (Terminal::ColorSupport() >= Terminal::Color::Palette256) {
116 if (Terminal::ColorSupport() == Terminal::Color::Palette1) {
117 type_ = ColorType::Palette1;
120 type_ = ColorType::Palette16;
121 red_ = GetColorInfo(Color::Palette256(red_)).index_16;
131Color::Color(uint8_t red, uint8_t green, uint8_t blue, uint8_t alpha)
137 if (Terminal::ColorSupport() == Terminal::Color::TrueColor) {
140 if (Terminal::ColorSupport() == Terminal::Color::Palette1) {
141 type_ = ColorType::Palette1;
146 const int max_distance = 256 * 256 * 3;
147 int closest = max_distance;
149 const int database_begin = 16;
150 const int database_end = 256;
151 for (
int i = database_begin; i < database_end; ++i) {
152 const ColorInfo color_info = GetColorInfo(Color::Palette256(i));
153 const int dr = color_info.red - red;
154 const int dg = color_info.green - green;
155 const int db = color_info.blue - blue;
156 const int dist = dr * dr + dg * dg + db * db;
157 if (closest > dist) {
163 if (Terminal::ColorSupport() == Terminal::Color::Palette256) {
164 type_ = ColorType::Palette256;
167 type_ = ColorType::Palette16;
168 red_ = GetColorInfo(Color::Palette256(best)).index_16;
179Color Color::RGB(uint8_t red, uint8_t green, uint8_t blue) {
180 return RGBA(red, green, blue, 255);
191Color Color::RGBA(uint8_t red, uint8_t green, uint8_t blue, uint8_t alpha) {
192 return {red, green, blue, alpha};
203Color Color::HSVA(uint8_t h, uint8_t s, uint8_t v, uint8_t alpha) {
204 uint8_t region = h / 43;
205 uint8_t remainder = (h - (region * 43)) * 6;
206 uint8_t p = (v * (255 - s)) >> 8;
207 uint8_t q = (v * (255 - ((s * remainder) >> 8))) >> 8;
208 uint8_t t = (v * (255 - ((s * (255 - remainder)) >> 8))) >> 8;
212 case 0:
return Color(v,t,p, alpha);
213 case 1:
return Color(q,v,p, alpha);
214 case 2:
return Color(p,v,t, alpha);
215 case 3:
return Color(p,q,v, alpha);
216 case 4:
return Color(t,p,v, alpha);
217 case 5:
return Color(v,p,q, alpha);
220 return {0, 0, 0, alpha};
230Color Color::HSV(uint8_t h, uint8_t s, uint8_t v) {
231 return HSVA(h, s, v, 255);
235Color Color::Interpolate(
float t,
const Color& a,
const Color& b) {
236 if (a.type_ == ColorType::Palette1 ||
237 b.type_ == ColorType::Palette1) {
246 [](
const Color& color) -> std::tuple<uint8_t, uint8_t, uint8_t> {
247 switch (color.type_) {
248 case ColorType::Palette1: {
251 case ColorType::Palette16: {
252 const ColorInfo info = GetColorInfo(Color::Palette16(color.red_));
253 return {info.red, info.green, info.blue};
255 case ColorType::Palette256: {
256 const ColorInfo info = GetColorInfo(Color::Palette256(color.red_));
257 return {info.red, info.green, info.blue};
259 case ColorType::TrueColor:
261 return {color.red_, color.green_, color.blue_};
266 const auto [a_r, a_g, a_b] = to_rgb(a);
267 const auto [b_r, b_g, b_b] = to_rgb(b);
271 auto interp = [t](uint8_t a_u, uint8_t b_u) {
272 constexpr float gamma = 2.2F;
273 const float a_f = std::pow(a_u, gamma);
274 const float b_f = std::pow(b_u, gamma);
275 const float c_f = a_f * (1.0F - t) +
277 return static_cast<uint8_t
>(std::pow(c_f, 1.F / gamma));
279 return Color::RGB(interp(a_r, b_r),
286Color Color::Blend(
const Color& lhs,
const Color& rhs) {
287 Color out = Interpolate(
float(rhs.alpha_) / 255.F, lhs, rhs);
288 out.alpha_ = lhs.alpha_ + rhs.alpha_ - lhs.alpha_ * rhs.alpha_ / 255;
294Color
operator""_rgb(
unsigned long long int combined) {
296 auto const red =
static_cast<uint8_t
>(combined >> 16U);
297 auto const green =
static_cast<uint8_t
>(combined >> 8U);
298 auto const blue =
static_cast<uint8_t
>(combined);
299 return {red, green, blue};
The FTXUI ftxui:: namespace.
The FTXUI ftxui::literals:: namespace.