FTXUI 6.1.9
C++ functional terminal UI.
Loading...
Searching...
No Matches
screen/color.cpp
Go to the documentation of this file.
1// Copyright 2020 Arthur Sonzogni. All rights reserved.
2// このソースコードの使用は、LICENSE ファイルにある MIT ライセンスによって管理されています。
4
5#include <array> // for array
6#include <cmath>
7#include <cstdint>
8#include <string>
9
10#include "ftxui/screen/color_info.hpp" // for GetColorInfo, ColorInfo
11#include "ftxui/screen/terminal.hpp" // for ColorSupport, Color, Palette256, TrueColor
12
13namespace ftxui {
14namespace {
15const std::array<const char*, 33> palette16code = {
16 "30", "40", //
17 "31", "41", //
18 "32", "42", //
19 "33", "43", //
20 "34", "44", //
21 "35", "45", //
22 "36", "46", //
23 "37", "47", //
24 "90", "100", //
25 "91", "101", //
26 "92", "102", //
27 "93", "103", //
28 "94", "104", //
29 "95", "105", //
30 "96", "106", //
31 "97", "107", //
32};
33
34} // namespace
35
36bool Color::operator==(const Color& rhs) const {
37 return red_ == rhs.red_ && green_ == rhs.green_ && blue_ == rhs.blue_ &&
38 type_ == rhs.type_;
39}
40
41bool Color::operator!=(const Color& rhs) const {
42 return !operator==(rhs);
43}
44
45std::string Color::Print(bool is_background_color) const {
46 if (is_background_color) {
47 switch (type_) {
48 case ColorType::Palette1:
49 return "49";
50 case ColorType::Palette16:
51 return palette16code[2 * red_ + 1]; // NOLINT
52 case ColorType::Palette256:
53 return "48;5;" + std::to_string(red_);
54 case ColorType::TrueColor:
55 return "48;2;" + std::to_string(red_) + ";" + std::to_string(green_) +
56 ";" + std::to_string(blue_);
57 }
58 } else {
59 switch (type_) {
60 case ColorType::Palette1:
61 return "39";
62 case ColorType::Palette16:
63 return palette16code[2 * red_]; // NOLINT
64 case ColorType::Palette256:
65 return "38;5;" + std::to_string(red_);
66 case ColorType::TrueColor:
67 return "38;2;" + std::to_string(red_) + ";" + std::to_string(green_) +
68 ";" + std::to_string(blue_);
69 }
70 }
71 // NOTREACHED();
72 return "";
73}
74
75/// @brief 透明な色を構築します。
76Color::Color() = default;
77
78/// @brief 透明な色を構築します。
79Color::Color(Palette1 /*value*/) : Color() {}
80
81/// @brief Palette16の色を使用して色を構築します。
83 : type_(ColorType::Palette16), red_(index), alpha_(255) {}
84
85/// @brief Palette256の色を使用して色を構築します。
87 : type_(ColorType::Palette256), red_(index), alpha_(255) {
88 if (Terminal::ColorSupport() >= Terminal::Color::Palette256) {
89 return;
90 }
91 type_ = ColorType::Palette16;
93}
94
95/// @brief RGB表現から色を構築します。
96/// https://en.wikipedia.org/wiki/RGB_color_model
97///
98/// @param red 赤の量 [0,255]
99/// @param green 緑の量 [0,255]
100/// @param blue 青の量 [0,255]
101/// @param alpha アルファの量 [0,255]
102Color::Color(uint8_t red, uint8_t green, uint8_t blue, uint8_t alpha)
103 : type_(ColorType::TrueColor),
104 red_(red),
105 green_(green),
106 blue_(blue),
107 alpha_(alpha) {
108 if (Terminal::ColorSupport() == Terminal::Color::TrueColor) {
109 return;
110 }
111
112 // Find the closest Color from the database:
113 const int max_distance = 256 * 256 * 3;
114 int closest = max_distance;
115 int best = 0;
116 const int database_begin = 16;
117 const int database_end = 256;
118 for (int i = database_begin; i < database_end; ++i) {
119 const ColorInfo color_info = GetColorInfo(Color::Palette256(i));
120 const int dr = color_info.red - red;
121 const int dg = color_info.green - green;
122 const int db = color_info.blue - blue;
123 const int dist = dr * dr + dg * dg + db * db;
124 if (closest > dist) {
125 closest = dist;
126 best = i;
127 }
128 }
129
130 if (Terminal::ColorSupport() == Terminal::Color::Palette256) {
131 type_ = ColorType::Palette256;
132 red_ = best;
133 } else {
134 type_ = ColorType::Palette16;
136 }
137}
138
139/// @brief RGB表現から色を構築します。
140/// https://en.wikipedia.org/wiki/RGB_color_model
141///
142/// @param red 赤の量 [0,255]
143/// @param green 緑の量 [0,255]
144/// @param blue 青の量 [0,255]
145// static
146Color Color::RGB(uint8_t red, uint8_t green, uint8_t blue) {
147 return RGBA(red, green, blue, 255);
148}
149
150/// @brief RGBA表現から色を構築します。
151/// https://en.wikipedia.org/wiki/RGB_color_model
152/// @param red 赤の量 [0,255]
153/// @param green 緑の量 [0,255]
154/// @param blue 青の量 [0,255]
155/// @param alpha アルファの量 [0,255]
156/// @see Color::RGB
157// static
158Color Color::RGBA(uint8_t red, uint8_t green, uint8_t blue, uint8_t alpha) {
159 return {red, green, blue, alpha};
160}
161
162/// @brief HSV表現から色を構築します。
163/// https://en.wikipedia.org/wiki/HSL_and_HSV
164///
165/// @param h 色相 [0,255]
166/// @param s 彩度 [0,255]。
167/// @param v 明度 [0,255]
168/// @param alpha アルファの量 [0,255]
169// static
170Color Color::HSVA(uint8_t h, uint8_t s, uint8_t v, uint8_t alpha) {
171 uint8_t region = h / 43; // NOLINT
172 uint8_t remainder = (h - (region * 43)) * 6; // NOLINT
173 uint8_t p = (v * (255 - s)) >> 8; // NOLINT
174 uint8_t q = (v * (255 - ((s * remainder) >> 8))) >> 8; // NOLINT
175 uint8_t t = (v * (255 - ((s * (255 - remainder)) >> 8))) >> 8; // NOLINT
176
177 // clang-format off
178 switch (region) { // NOLINT
179 case 0: return Color(v,t,p, alpha); // NOLINT
180 case 1: return Color(q,v,p, alpha); // NOLINT
181 case 2: return Color(p,v,t, alpha); // NOLINT
182 case 3: return Color(p,q,v, alpha); // NOLINT
183 case 4: return Color(t,p,v, alpha); // NOLINT
184 case 5: return Color(v,p,q, alpha); // NOLINT
185 } // NOLINT
186 // clang-format on
187 return {0, 0, 0, alpha};
188}
189
190/// @brief HSV表現から色を構築します。
191/// https://en.wikipedia.org/wiki/HSL_and_HSV
192///
193/// @param h 色相 [0,255]
194/// @param s 彩度 [0,255]。
195/// @param v 明度 [0,255]
196// static
197Color Color::HSV(uint8_t h, uint8_t s, uint8_t v) {
198 return HSVA(h, s, v, 255);
199}
200
201// static
202Color Color::Interpolate(float t, const Color& a, const Color& b) {
203 if (a.type_ == ColorType::Palette1 || //
204 b.type_ == ColorType::Palette1) {
205 if (t < 0.5F) { // NOLINT
206 return a;
207 } else {
208 return b;
209 }
210 }
211
212 auto get_color = [](const Color& color, //
213 uint8_t* red, uint8_t* green, uint8_t* blue) {
214 switch (color.type_) {
215 case ColorType::Palette1: {
216 return;
217 }
218
219 case ColorType::Palette16: {
220 const ColorInfo info = GetColorInfo(Color::Palette16(color.red_));
221 *red = info.red;
222 *green = info.green;
223 *blue = info.blue;
224 return;
225 }
226
227 case ColorType::Palette256: {
228 const ColorInfo info = GetColorInfo(Color::Palette256(color.red_));
229 *red = info.red;
230 *green = info.green;
231 *blue = info.blue;
232 return;
233 }
234
235 case ColorType::TrueColor:
236 default: {
237 *red = color.red_;
238 *green = color.green_;
239 *blue = color.blue_;
240 return;
241 }
242 }
243 };
244
245 uint8_t a_r = 0;
246 uint8_t a_g = 0;
247 uint8_t a_b = 0;
248 uint8_t b_r = 0;
249 uint8_t b_g = 0;
250 uint8_t b_b = 0;
251 get_color(a, &a_r, &a_g, &a_b);
252 get_color(b, &b_r, &b_g, &b_b);
253
254 // ガンマ補正:
255 // https://en.wikipedia.org/wiki/Gamma_correction
256 auto interp = [t](uint8_t a_u, uint8_t b_u) {
257 constexpr float gamma = 2.2F;
258 const float a_f = powf(a_u, gamma);
259 const float b_f = powf(b_u, gamma);
260 const float c_f = a_f * (1.0F - t) + //
261 b_f * t;
262 return static_cast<uint8_t>(powf(c_f, 1.F / gamma));
263 };
264 return Color::RGB(interp(a_r, b_r), //
265 interp(a_g, b_g), //
266 interp(a_b, b_b)); //
267}
268
269/// @brief アルファチャンネルを使用して2つの色をブレンドします。
270// static
271Color Color::Blend(const Color& lhs, const Color& rhs) {
272 Color out = Interpolate(float(rhs.alpha_) / 255.F, lhs, rhs);
273 out.alpha_ = lhs.alpha_ + rhs.alpha_ - lhs.alpha_ * rhs.alpha_ / 255;
274 return out;
275}
276
277inline namespace literals {
278
279Color operator""_rgb(unsigned long long int combined) {
280 // assert(combined <= 0xffffffU);
281 auto const red = static_cast<uint8_t>(combined >> 16U);
282 auto const green = static_cast<uint8_t>(combined >> 8U);
283 auto const blue = static_cast<uint8_t>(combined);
284 return {red, green, blue};
285}
286
287} // namespace literals
288
289} // namespace ftxui
Decorator color(Color)
前景色を使用して装飾します。
Color()
透明な色を構築します。
static Color HSV(uint8_t hue, uint8_t saturation, uint8_t value)
HSV表現から色を構築します。 https://en.wikipedia.org/wiki/HSL_and_HSV.
static Color RGBA(uint8_t red, uint8_t green, uint8_t blue, uint8_t alpha)
RGBA表現から色を構築します。 https://en.wikipedia.org/wiki/RGB_color_model.
static Color Blend(const Color &lhs, const Color &rhs)
アルファチャンネルを使用して2つの色をブレンドします。
bool operator!=(const Color &rhs) const
bool operator==(const Color &rhs) const
static Color RGB(uint8_t red, uint8_t green, uint8_t blue)
RGB表現から色を構築します。 https://en.wikipedia.org/wiki/RGB_color_model.
std::string Print(bool is_background_color) const
static Color Interpolate(float t, const Color &a, const Color &b)
static Color HSVA(uint8_t hue, uint8_t saturation, uint8_t value, uint8_t alpha)
HSV表現から色を構築します。 https://en.wikipedia.org/wiki/HSL_and_HSV.
Colorは、ターミナルユーザーインターフェースにおける色を表すクラスです。
Definition color.hpp:25
ColorInfoは、ターミナルのカラーパレットに関する情報を含む構造体です。
FTXUI ftxui:: 名前空間
Definition animation.hpp:9
ColorInfo GetColorInfo(Color::Palette256 index)
FTXUI ftxui::literals::名前空間