2020-09-02 17:32:22 +08:00
|
|
|
#include "ftxui/screen/color.hpp"
|
2020-12-23 21:45:57 +08:00
|
|
|
#include "ftxui/screen/color_info.hpp"
|
2020-09-02 17:32:22 +08:00
|
|
|
#include "ftxui/screen/string.hpp"
|
2020-12-23 21:45:57 +08:00
|
|
|
#include "ftxui/screen/terminal.hpp"
|
2020-09-02 17:32:22 +08:00
|
|
|
|
|
|
|
namespace ftxui {
|
|
|
|
|
2020-10-17 04:31:24 +08:00
|
|
|
namespace {
|
|
|
|
const wchar_t* palette16code[16][2] = {
|
|
|
|
{L"30", L"40"}, {L"31", L"41"}, {L"32", L"42"}, {L"33", L"43"},
|
|
|
|
{L"34", L"44"},
|
|
|
|
|
|
|
|
{L"35", L"45"}, {L"36", L"46"}, {L"37", L"47"},
|
|
|
|
|
|
|
|
{L"90", L"100"}, {L"91", L"101"}, {L"92", L"102"}, {L"93", L"103"},
|
|
|
|
{L"94", L"104"}, {L"95", L"105"}, {L"96", L"106"}, {L"97", L"107"},
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2020-09-02 17:32:22 +08:00
|
|
|
bool Color::operator==(const Color& rhs) const {
|
|
|
|
return red_ == rhs.red_ && green_ == rhs.green_ && blue_ == rhs.blue_ &&
|
|
|
|
type_ == rhs.type_;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Color::operator!=(const Color& rhs) const {
|
|
|
|
return !operator==(rhs);
|
|
|
|
}
|
|
|
|
|
|
|
|
std::wstring Color::Print(bool is_background_color) const {
|
|
|
|
switch (type_) {
|
2020-10-17 04:31:24 +08:00
|
|
|
case ColorType::Palette1:
|
|
|
|
return is_background_color ? L"49" : L"39";
|
|
|
|
|
2020-09-02 17:32:22 +08:00
|
|
|
case ColorType::Palette16:
|
2020-10-17 04:31:24 +08:00
|
|
|
return palette16code[index_][is_background_color];
|
2020-09-02 17:32:22 +08:00
|
|
|
|
|
|
|
case ColorType::Palette256:
|
2020-12-23 21:45:57 +08:00
|
|
|
return (is_background_color ? L"48;5;" : L"38;5;") + to_wstring(index_);
|
2020-09-02 17:32:22 +08:00
|
|
|
|
|
|
|
case ColorType::TrueColor:
|
2020-10-17 04:31:24 +08:00
|
|
|
return (is_background_color ? L"48;2;" : L"38;2;") //
|
|
|
|
+ to_wstring(red_) + L";" //
|
|
|
|
+ to_wstring(green_) + L";" //
|
|
|
|
+ to_wstring(blue_); //
|
2020-09-02 17:32:22 +08:00
|
|
|
}
|
|
|
|
return L"";
|
|
|
|
}
|
|
|
|
|
2020-09-06 19:43:24 +08:00
|
|
|
/// @brief Build a transparent color.
|
|
|
|
/// @ingroup screen
|
2020-10-17 04:31:24 +08:00
|
|
|
Color::Color() : type_(ColorType::Palette1) {}
|
|
|
|
|
|
|
|
/// @brief Build a transparent color.
|
|
|
|
/// @ingroup screen
|
|
|
|
Color::Color(Palette1) : type_(ColorType::Palette1) {}
|
2020-09-06 19:43:24 +08:00
|
|
|
|
|
|
|
/// @brief Build a transparent using Palette16 colors.
|
|
|
|
/// @ingroup screen
|
2020-09-02 17:32:22 +08:00
|
|
|
Color::Color(Palette16 index) : type_(ColorType::Palette16), index_(index) {}
|
2020-09-06 19:43:24 +08:00
|
|
|
|
|
|
|
/// @brief Build a transparent using Palette256 colors.
|
|
|
|
/// @ingroup screen
|
2020-12-23 21:45:57 +08:00
|
|
|
Color::Color(Palette256 index) : type_(ColorType::Palette256), index_(index) {
|
|
|
|
if (Terminal::ColorSupport() >= Terminal::Color::Palette256)
|
|
|
|
return;
|
|
|
|
type_ = ColorType::Palette16;
|
|
|
|
index_ = GetColorInfo(Color::Palette256(index_)).index_16;
|
|
|
|
}
|
2020-09-06 19:43:24 +08:00
|
|
|
|
|
|
|
/// @brief Build a Color from its RGB representation.
|
|
|
|
/// https://en.wikipedia.org/wiki/RGB_color_model
|
|
|
|
///
|
|
|
|
/// @param red The quantity of red [0,255]
|
|
|
|
/// @param green The quantity of green [0,255]
|
|
|
|
/// @param blue The quantity of blue [0,255]
|
|
|
|
/// @ingroup screen
|
2020-09-02 17:32:22 +08:00
|
|
|
Color::Color(uint8_t red, uint8_t green, uint8_t blue)
|
2020-12-23 21:45:57 +08:00
|
|
|
: type_(ColorType::TrueColor), red_(red), green_(green), blue_(blue) {
|
|
|
|
if (Terminal::ColorSupport() == Terminal::Color::TrueColor)
|
|
|
|
return;
|
|
|
|
|
|
|
|
int closest = 256 * 256 * 3;
|
|
|
|
int best = 0;
|
|
|
|
for (int i = 16; i < 256; ++i) {
|
|
|
|
ColorInfo color_info = GetColorInfo(Color::Palette256(i));
|
|
|
|
int dr = color_info.red - red;
|
|
|
|
int dg = color_info.green - green;
|
|
|
|
int db = color_info.blue - blue;
|
|
|
|
int dist = dr * dr + dg * dg + db * db;
|
|
|
|
if (closest > dist) {
|
|
|
|
closest = dist;
|
|
|
|
best = i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Terminal::ColorSupport() == Terminal::Color::Palette256) {
|
|
|
|
type_ = ColorType::Palette256;
|
|
|
|
index_ = best;
|
|
|
|
} else {
|
|
|
|
type_ = ColorType::Palette16;
|
|
|
|
index_ = GetColorInfo(Color::Palette256(best)).index_16;
|
|
|
|
}
|
|
|
|
}
|
2020-09-02 17:32:22 +08:00
|
|
|
|
2020-09-06 19:43:24 +08:00
|
|
|
/// @brief Build a Color from its RGB representation.
|
|
|
|
/// https://en.wikipedia.org/wiki/RGB_color_model
|
|
|
|
///
|
|
|
|
/// @param red The quantity of red [0,255]
|
|
|
|
/// @param green The quantity of green [0,255]
|
|
|
|
/// @param blue The quantity of blue [0,255]
|
|
|
|
/// @ingroup screen
|
2020-09-02 17:32:22 +08:00
|
|
|
// static
|
|
|
|
Color Color::RGB(uint8_t red, uint8_t green, uint8_t blue) {
|
|
|
|
return Color(red, green, blue);
|
|
|
|
}
|
|
|
|
|
2020-09-06 19:43:24 +08:00
|
|
|
/// @brief Build a Color from its HSV representation.
|
|
|
|
/// https://en.wikipedia.org/wiki/HSL_and_HSV
|
|
|
|
///
|
2021-07-10 20:23:46 +08:00
|
|
|
/// @param h The hue of the color [0,255]
|
|
|
|
/// @param s The "colorfulness" [0,255].
|
|
|
|
/// @param v The "Lightness" [0,255]
|
2020-09-06 19:43:24 +08:00
|
|
|
/// @ingroup screen
|
2020-09-02 17:32:22 +08:00
|
|
|
// static
|
|
|
|
Color Color::HSV(uint8_t h, uint8_t s, uint8_t v) {
|
|
|
|
if (s == 0)
|
|
|
|
return Color(v, v, v);
|
|
|
|
|
|
|
|
uint8_t region = h / 43;
|
|
|
|
uint8_t remainder = (h - (region * 43)) * 6;
|
|
|
|
uint8_t p = (v * (255 - s)) >> 8;
|
|
|
|
uint8_t q = (v * (255 - ((s * remainder) >> 8))) >> 8;
|
|
|
|
uint8_t t = (v * (255 - ((s * (255 - remainder)) >> 8))) >> 8;
|
|
|
|
|
|
|
|
// clang-format off
|
|
|
|
switch (region) {
|
|
|
|
case 0: return Color(v,t,p);
|
|
|
|
case 1: return Color(q,v,p);
|
|
|
|
case 2: return Color(p,v,t);
|
|
|
|
case 3: return Color(p,q,v);
|
|
|
|
case 4: return Color(t,p,v);
|
|
|
|
case 5: return Color(v,p,q);
|
|
|
|
}
|
|
|
|
// clang-format on
|
|
|
|
|
|
|
|
return Color(0, 0, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace ftxui
|
|
|
|
|
|
|
|
// Copyright 2020 Arthur Sonzogni. All rights reserved.
|
|
|
|
// Use of this source code is governed by the MIT license that can be found in
|
|
|
|
// the LICENSE file.
|