FTXUI
6.1.9
C++ functional terminal UI.
Toggle main menu visibility
Loading...
Searching...
No Matches
color.cpp
Go to the documentation of this file.
1
// Copyright 2020 Arthur Sonzogni. All rights reserved.
2
// Use of this source code is governed by the MIT license that can be found in
3
// the LICENSE file.
4
#include "
ftxui/screen/color.hpp
"
5
6
#include <array>
// for array
7
#include <cmath>
8
#include <cstdint>
9
#include <string>
10
11
#include "
ftxui/screen/color_info.hpp
"
// for GetColorInfo, ColorInfo
12
#include "
ftxui/screen/terminal.hpp
"
// for ColorSupport, Color, Palette256, TrueColor
13
14
namespace
ftxui
{
15
namespace
{
16
const
std::array<const char*, 33> palette16code = {
17
"30"
,
"40"
,
//
18
"31"
,
"41"
,
//
19
"32"
,
"42"
,
//
20
"33"
,
"43"
,
//
21
"34"
,
"44"
,
//
22
"35"
,
"45"
,
//
23
"36"
,
"46"
,
//
24
"37"
,
"47"
,
//
25
"90"
,
"100"
,
//
26
"91"
,
"101"
,
//
27
"92"
,
"102"
,
//
28
"93"
,
"103"
,
//
29
"94"
,
"104"
,
//
30
"95"
,
"105"
,
//
31
"96"
,
"106"
,
//
32
"97"
,
"107"
,
//
33
};
34
35
}
// namespace
36
37
bool
Color::operator==
(
const
Color
& rhs)
const
{
38
return
red_ == rhs.red_ && green_ == rhs.green_ && blue_ == rhs.blue_ &&
39
type_ == rhs.type_;
40
}
41
42
bool
Color::operator!=
(
const
Color
& rhs)
const
{
43
return
!
operator==
(rhs);
44
}
45
46
std::string
Color::Print
(
bool
is_background_color)
const
{
47
if
(is_background_color) {
48
switch
(type_) {
49
case
ColorType::Palette1:
50
return
"49"
;
51
case
ColorType::Palette16:
52
return
palette16code[2 * red_ + 1];
// NOLINT
53
case
ColorType::Palette256:
54
return
"48;5;"
+ std::to_string(red_);
55
case
ColorType::TrueColor:
56
return
"48;2;"
+ std::to_string(red_) +
";"
+ std::to_string(green_) +
57
";"
+ std::to_string(blue_);
58
}
59
}
else
{
60
switch
(type_) {
61
case
ColorType::Palette1:
62
return
"39"
;
63
case
ColorType::Palette16:
64
return
palette16code[2 * red_];
// NOLINT
65
case
ColorType::Palette256:
66
return
"38;5;"
+ std::to_string(red_);
67
case
ColorType::TrueColor:
68
return
"38;2;"
+ std::to_string(red_) +
";"
+ std::to_string(green_) +
69
";"
+ std::to_string(blue_);
70
}
71
}
72
// NOTREACHED();
73
return
""
;
74
}
75
76
/// @brief Build a transparent color.
77
/// @ingroup screen
78
Color::Color
() =
default
;
79
80
/// @brief Build a transparent color.
81
/// @ingroup screen
82
Color::Color
(
Palette1
/*value*/
) :
Color
() {}
83
84
/// @brief Build a color using the Palette16 colors.
85
/// @ingroup screen
86
Color::Color
(
Palette16
index)
87
: type_(ColorType::
Palette16
), red_(index), alpha_(255) {}
88
89
/// @brief Build a color using Palette256 colors.
90
/// @ingroup screen
91
Color::Color
(
Palette256
index)
92
: type_(ColorType::
Palette256
), red_(index), alpha_(255) {
93
if
(
Terminal::ColorSupport
() >=
Terminal::Color::Palette256
) {
94
return
;
95
}
96
type_ = ColorType::Palette16;
97
red_ =
GetColorInfo
(
Color::Palette256
(red_)).
index_16
;
98
}
99
100
/// @brief Build a Color from its RGB representation.
101
/// https://en.wikipedia.org/wiki/RGB_color_model
102
///
103
/// @param red The quantity of red [0,255]
104
/// @param green The quantity of green [0,255]
105
/// @param blue The quantity of blue [0,255]
106
/// @param alpha The quantity of alpha [0,255]
107
/// @ingroup screen
108
Color::Color
(uint8_t red, uint8_t green, uint8_t blue, uint8_t alpha)
109
: type_(ColorType::TrueColor),
110
red_(red),
111
green_(green),
112
blue_(blue),
113
alpha_(alpha) {
114
if
(
Terminal::ColorSupport
() ==
Terminal::Color::TrueColor
) {
115
return
;
116
}
117
118
// Find the closest Color from the database:
119
const
int
max_distance = 256 * 256 * 3;
120
int
closest = max_distance;
121
int
best = 0;
122
const
int
database_begin = 16;
123
const
int
database_end = 256;
124
for
(
int
i = database_begin; i < database_end; ++i) {
125
const
ColorInfo
color_info =
GetColorInfo
(
Color::Palette256
(i));
126
const
int
dr = color_info.
red
- red;
127
const
int
dg = color_info.
green
- green;
128
const
int
db = color_info.
blue
- blue;
129
const
int
dist = dr * dr + dg * dg + db * db;
130
if
(closest > dist) {
131
closest = dist;
132
best = i;
133
}
134
}
135
136
if
(
Terminal::ColorSupport
() ==
Terminal::Color::Palette256
) {
137
type_ = ColorType::Palette256;
138
red_ = best;
139
}
else
{
140
type_ = ColorType::Palette16;
141
red_ =
GetColorInfo
(
Color::Palette256
(best)).
index_16
;
142
}
143
}
144
145
/// @brief Build a Color from its RGB representation.
146
/// https://en.wikipedia.org/wiki/RGB_color_model
147
///
148
/// @param red The quantity of red [0,255]
149
/// @param green The quantity of green [0,255]
150
/// @param blue The quantity of blue [0,255]
151
/// @ingroup screen
152
// static
153
Color
Color::RGB
(uint8_t red, uint8_t green, uint8_t blue) {
154
return
RGBA
(red, green, blue, 255);
155
}
156
157
/// @brief Build a Color from its RGBA representation.
158
/// https://en.wikipedia.org/wiki/RGB_color_model
159
/// @param red The quantity of red [0,255]
160
/// @param green The quantity of green [0,255]
161
/// @param blue The quantity of blue [0,255]
162
/// @param alpha The quantity of alpha [0,255]
163
/// @ingroup screen
164
/// @see Color::RGB
165
// static
166
Color
Color::RGBA
(uint8_t red, uint8_t green, uint8_t blue, uint8_t alpha) {
167
return
{red, green, blue, alpha};
168
}
169
170
/// @brief Build a Color from its HSV representation.
171
/// https://en.wikipedia.org/wiki/HSL_and_HSV
172
///
173
/// @param h The hue of the color [0,255]
174
/// @param s The "colorfulness" [0,255].
175
/// @param v The "Lightness" [0,255]
176
/// @param alpha The quantity of alpha [0,255]
177
/// @ingroup screen
178
// static
179
Color
Color::HSVA
(uint8_t h, uint8_t s, uint8_t v, uint8_t alpha) {
180
uint8_t region = h / 43;
// NOLINT
181
uint8_t remainder = (h - (region * 43)) * 6;
// NOLINT
182
uint8_t p = (v * (255 - s)) >> 8;
// NOLINT
183
uint8_t q = (v * (255 - ((s * remainder) >> 8))) >> 8;
// NOLINT
184
uint8_t t = (v * (255 - ((s * (255 - remainder)) >> 8))) >> 8;
// NOLINT
185
186
// clang-format off
187
switch
(region) {
// NOLINT
188
case
0:
return
Color
(v,t,p, alpha);
// NOLINT
189
case
1:
return
Color
(q,v,p, alpha);
// NOLINT
190
case
2:
return
Color
(p,v,t, alpha);
// NOLINT
191
case
3:
return
Color
(p,q,v, alpha);
// NOLINT
192
case
4:
return
Color
(t,p,v, alpha);
// NOLINT
193
case
5:
return
Color
(v,p,q, alpha);
// NOLINT
194
}
// NOLINT
195
// clang-format on
196
return
{0, 0, 0, alpha};
197
}
198
199
/// @brief Build a Color from its HSV representation.
200
/// https://en.wikipedia.org/wiki/HSL_and_HSV
201
///
202
/// @param h The hue of the color [0,255]
203
/// @param s The "colorfulness" [0,255].
204
/// @param v The "Lightness" [0,255]
205
/// @ingroup screen
206
// static
207
Color
Color::HSV
(uint8_t h, uint8_t s, uint8_t v) {
208
return
HSVA
(h, s, v, 255);
209
}
210
211
// static
212
Color
Color::Interpolate
(
float
t,
const
Color
& a,
const
Color
& b) {
213
if
(a.type_ == ColorType::Palette1 ||
//
214
b.type_ == ColorType::Palette1) {
215
if
(t < 0.5F) {
// NOLINT
216
return
a;
217
}
else
{
218
return
b;
219
}
220
}
221
222
auto
get_color = [](
const
Color
&
color
,
//
223
uint8_t* red, uint8_t* green, uint8_t* blue) {
224
switch
(
color
.type_) {
225
case
ColorType::Palette1: {
226
return
;
227
}
228
229
case
ColorType::Palette16: {
230
const
ColorInfo
info =
GetColorInfo
(
Color::Palette16
(
color
.red_));
231
*red = info.
red
;
232
*green = info.
green
;
233
*blue = info.
blue
;
234
return
;
235
}
236
237
case
ColorType::Palette256: {
238
const
ColorInfo
info =
GetColorInfo
(
Color::Palette256
(
color
.red_));
239
*red = info.
red
;
240
*green = info.
green
;
241
*blue = info.
blue
;
242
return
;
243
}
244
245
case
ColorType::TrueColor:
246
default
: {
247
*red =
color
.red_;
248
*green =
color
.green_;
249
*blue =
color
.blue_;
250
return
;
251
}
252
}
253
};
254
255
uint8_t a_r = 0;
256
uint8_t a_g = 0;
257
uint8_t a_b = 0;
258
uint8_t b_r = 0;
259
uint8_t b_g = 0;
260
uint8_t b_b = 0;
261
get_color(a, &a_r, &a_g, &a_b);
262
get_color(b, &b_r, &b_g, &b_b);
263
264
// Gamma correction:
265
// https://en.wikipedia.org/wiki/Gamma_correction
266
auto
interp = [t](uint8_t a_u, uint8_t b_u) {
267
constexpr
float
gamma = 2.2F;
268
const
float
a_f = powf(a_u, gamma);
269
const
float
b_f = powf(b_u, gamma);
270
const
float
c_f = a_f * (1.0F - t) +
//
271
b_f * t;
272
return
static_cast<
uint8_t
>
(powf(c_f, 1.F / gamma));
273
};
274
return
Color::RGB
(interp(a_r, b_r),
//
275
interp(a_g, b_g),
//
276
interp(a_b, b_b));
//
277
}
278
279
/// @brief Blend two colors together using the alpha channel.
280
// static
281
Color
Color::Blend
(
const
Color
& lhs,
const
Color
& rhs) {
282
Color
out =
Interpolate
(
float
(rhs.alpha_) / 255.F, lhs, rhs);
283
out.alpha_ = lhs.alpha_ + rhs.alpha_ - lhs.alpha_ * rhs.alpha_ / 255;
284
return
out;
285
}
286
287
inline
namespace
literals
{
288
289
Color
operator
""
_rgb(
unsigned
long
long
int
combined) {
290
// assert(combined <= 0xffffffU);
291
auto
const
red =
static_cast<
uint8_t
>
(combined >> 16U);
292
auto
const
green =
static_cast<
uint8_t
>
(combined >> 8U);
293
auto
const
blue =
static_cast<
uint8_t
>
(combined);
294
return
{red, green, blue};
295
}
296
297
}
// namespace literals
298
299
}
// namespace ftxui
ftxui::Color
A class representing terminal colors.
Definition
color.hpp:20
ftxui::Color::Color
Color()
Build a transparent color.
ftxui::Color::HSV
static Color HSV(uint8_t hue, uint8_t saturation, uint8_t value)
Build a Color from its HSV representation. https://en.wikipedia.org/wiki/HSL_and_HSV.
Definition
color.cpp:207
ftxui::Color::RGBA
static Color RGBA(uint8_t red, uint8_t green, uint8_t blue, uint8_t alpha)
Build a Color from its RGBA representation. https://en.wikipedia.org/wiki/RGB_color_model.
Definition
color.cpp:166
ftxui::Color::Blend
static Color Blend(const Color &lhs, const Color &rhs)
Blend two colors together using the alpha channel.
Definition
color.cpp:281
ftxui::Color::operator!=
bool operator!=(const Color &rhs) const
Definition
color.cpp:42
ftxui::Color::operator==
bool operator==(const Color &rhs) const
Definition
color.cpp:37
ftxui::Color::Palette1
Palette1
Definition
color.hpp:47
ftxui::Color::RGB
static Color RGB(uint8_t red, uint8_t green, uint8_t blue)
Build a Color from its RGB representation. https://en.wikipedia.org/wiki/RGB_color_model.
Definition
color.cpp:153
ftxui::Color::Palette256
Palette256
Definition
color.hpp:70
ftxui::Color::Print
std::string Print(bool is_background_color) const
Definition
color.cpp:46
ftxui::Color::Palette16
Palette16
Definition
color.hpp:51
ftxui::Color::Interpolate
static Color Interpolate(float t, const Color &a, const Color &b)
Definition
color.cpp:212
ftxui::Color::HSVA
static Color HSVA(uint8_t hue, uint8_t saturation, uint8_t value, uint8_t alpha)
Build a Color from its HSV representation. https://en.wikipedia.org/wiki/HSL_and_HSV.
Definition
color.cpp:179
color.hpp
color_info.hpp
ftxui::Terminal::TrueColor
@ TrueColor
Definition
terminal.hpp:21
ftxui::Terminal::Palette256
@ Palette256
Definition
terminal.hpp:20
ftxui::Terminal::ColorSupport
Color ColorSupport()
Get the color support of the terminal.
Definition
terminal.cpp:130
ftxui::literals
Definition
color.hpp:335
ftxui
Definition
animation.hpp:10
ftxui::ColorInfo::blue
uint8_t blue
Definition
color_info.hpp:18
ftxui::ColorInfo::index_16
uint8_t index_16
Definition
color_info.hpp:15
ftxui::GetColorInfo
ColorInfo GetColorInfo(Color::Palette256 index)
Definition
color_info.cpp:272
ftxui::ColorInfo::green
uint8_t green
Definition
color_info.hpp:17
ftxui::ColorInfo::red
uint8_t red
Definition
color_info.hpp:16
ftxui::color
Decorator color(Color)
Decorate using a foreground color.
Definition
color.cpp:110
ftxui::ColorInfo
Definition
color_info.hpp:12
terminal.hpp