cpp-terminal 1.0.0
Small C++ library for writing multiplatform terminal applications
Loading...
Searching...
No Matches
color.cpp
Go to the documentation of this file.
1/*
2* cpp-terminal
3* C++ library for writing multi-platform terminal applications.
4*
5* SPDX-FileCopyrightText: 2019-2024 cpp-terminal
6*
7* SPDX-License-Identifier: MIT
8*/
9
11
13
14bool Term::Color::operator==(const Term::Color& color) const
15{
16 if(color.getType() != getType()) { return false; }
17 if(getType() == Term::Color::Type::Bit24) { return m_bit24 == color.to24bits(); }
18 return m_bit8 == color.to8bits();
19}
20
21bool Term::Color::operator!=(const Term::Color& color) const { return !(*this == color); }
22
23Term::Color::Color() : m_bit8(0) {}
24
25Term::Color::Color(const Term::Color::Name& name) : m_Type(Type::Bit4), m_bit8(static_cast<std::uint8_t>(name)) {}
26
27Term::Color::Color(const std::uint8_t& color) : m_Type(Type::Bit8), m_bit8(color) {}
28
29Term::Color::Color(const std::uint8_t& r, const std::uint8_t& b, const std::uint8_t& g) : m_Type(Type::Bit24)
30{
31 // Hack for gcc4.7
32 m_bit24[0] = r;
33 m_bit24[1] = b;
34 m_bit24[2] = g;
35}
36
37Term::Color::Type Term::Color::getType() const { return m_Type; }
38
40{
41 if(getType() == Type::Bit3) { return static_cast<Term::Color::Name>(m_bit8); }
42 const Term::Color::Name ret{to4bits()};
43 if(ret >= Term::Color::Name::Gray) { return static_cast<Term::Color::Name>(static_cast<uint8_t>(ret) - static_cast<uint8_t>(Term::Color::Name::Gray)); }
44 return ret;
45}
46
47// Convert 24bits and 8bits to 4bits
49{
50 //https://ajalt.github.io/colormath/converter/
51 // clang-format off
52 static const constexpr std::array<std::uint8_t,256> table ={{
53 0, 1, 2, 3, 4, 5, 6, 7, 60, 61, 62, 63, 64, 65, 66, 67, 0, 4, 4, 4, 64, 64, 2, 6, 4, 4, 64, 64, 2, 2, 6, 4, 64, 64, 2, 2, 2, 6, 64, 64, 62, 62, 62, 62, 66, 64, 62, 62, 62, 62, 62, 66,
54 1, 5, 4, 4, 64, 64, 3, 60, 4, 4, 64, 64, 2, 2, 6, 4, 64, 64, 2, 2, 2, 6, 64, 64, 62, 62, 62, 62, 66, 64, 62, 62, 62, 62, 62, 66, 1, 1, 5, 4, 64, 64, 1, 1, 5, 4, 64, 64, 3, 3, 60, 4,
55 64, 64, 2, 2, 2, 6, 64, 64, 62, 62, 62, 62, 66, 64, 62, 62, 62, 62, 62, 66, 1, 1, 1, 5, 64, 64, 1, 1, 1, 5, 64, 64, 1, 1, 1, 5, 64, 64, 3, 3, 3, 7, 64, 64, 62, 62, 62, 62, 66, 64, 62, 62,
56 62, 62, 62, 66, 61, 61, 61, 61, 65, 64, 61, 61, 61, 61, 65, 64, 61, 61, 61, 61, 65, 64, 61, 61, 61, 61, 65, 64, 63, 63, 63, 63, 7, 64, 62, 62, 62, 62, 62, 66, 61, 61, 61, 61, 61, 65, 61, 61, 61, 61, 61, 65,
57 61, 61, 61, 61, 61, 65, 61, 61, 61, 61, 61, 65, 61, 61, 61, 61, 61, 65, 63, 63, 63, 63, 63, 67, 0, 0, 0, 0, 0, 0, 60, 60, 60, 60, 60, 60, 7, 7, 7, 7, 7, 7, 67, 67, 67, 67, 67, 67}};
58 // clang-format on
59 if((getType() == Term::Color::Type::Bit24) || (getType() == Term::Color::Type::Bit8)) { return static_cast<Term::Color::Name>(table[to8bits()]); }
60 return static_cast<Term::Color::Name>(m_bit8);
61}
62
63// Convert 24bits to 8bits
64std::uint8_t Term::Color::to8bits() const
65{
66 if(getType() == Term::Color::Type::Bit24)
67 {
68 // check gray scale in 24 steps
69 if(m_bit24[0] == m_bit24[1] && m_bit24[0] == m_bit24[2]) { return static_cast<std::uint8_t>(232 + m_bit24[0] / 32 + m_bit24[1] / 32 + m_bit24[2] / 32); }
70 // normal color space
71 return static_cast<std::uint8_t>(16 + 36 * (m_bit24[0] / 51) + 6 * (m_bit24[1] / 51) + (m_bit24[2] / 51));
72 }
73 return m_bit8;
74}
75
76// Nothing to do
77std::array<std::uint8_t, 3> Term::Color::to24bits() const { return m_bit24; }
78
79std::string Term::color_bg(const Term::Color::Name& color) { return color_bg(Color(color)); }
80
81std::string Term::color_bg(const std::uint8_t& color) { return color_bg(Color(color)); }
82
83std::string Term::color_bg(const std::uint8_t& r, const std::uint8_t& g, const std::uint8_t& b) { return color_bg(Color(r, g, b)); }
84
85//https://unix.stackexchange.com/questions/212933/background-color-whitespace-when-end-of-the-terminal-reached
86//FIX maybe we need an other function without ␛[K if we want to modify background of part of the screen (Moving cursor and changing color )
87std::string Term::color_bg(const Color& color)
88{
89 if(color.getType() == Term::Color::Type::Unset || color.getType() == Term::Color::Type::NoColor) return "";
91 {
94 case Term::Terminfo::ColorMode::Bit3: return "\u001b[" + std::to_string(static_cast<uint8_t>(color.to3bits()) + 40) + "m\u001b[K";
95 case Term::Terminfo::ColorMode::Bit4: return "\u001b[" + std::to_string(static_cast<uint8_t>(color.to4bits()) + 40) + "m\u001b[K";
97 if(color.getType() == Term::Color::Type::Bit4 || color.getType() == Term::Color::Type::Bit3) return "\u001b[" + std::to_string(static_cast<uint8_t>(color.to4bits()) + 40) + "m\u001b[K";
98 else
99 return "\u001b[48;5;" + std::to_string(color.to8bits()) + "m\u001b[K";
101 if(color.getType() == Term::Color::Type::Bit3 || color.getType() == Term::Color::Type::Bit4) return "\u001b[" + std::to_string(static_cast<uint8_t>(color.to4bits()) + 40) + "m\u001b[K";
102 else if(color.getType() == Term::Color::Type::Bit8)
103 return "\u001b[48;5;" + std::to_string(color.to8bits()) + "m\u001b[K";
104 else
105 return "\u001b[48;2;" + std::to_string(color.to24bits()[0]) + ';' + std::to_string(color.to24bits()[1]) + ';' + std::to_string(color.to24bits()[2]) + "m\u001b[K";
106 default: return {};
107 }
108}
109
110std::string Term::color_fg(const Term::Color::Name& name) { return color_fg(Color(name)); }
111
112std::string Term::color_fg(const std::uint8_t& value) { return color_fg(Color(value)); }
113
114std::string Term::color_fg(const std::uint8_t& red, const std::uint8_t& green, const std::uint8_t& blue) { return color_fg(Color(red, green, blue)); }
115
116std::string Term::color_fg(const Color& color)
117{
118 if(color.getType() == Term::Color::Type::Unset || color.getType() == Term::Color::Type::NoColor) { return {}; }
120 {
123 case Term::Terminfo::ColorMode::Bit3: return "\u001b[" + std::to_string(static_cast<uint8_t>(color.to3bits()) + 30) + "m";
124 case Term::Terminfo::ColorMode::Bit4: return "\u001b[" + std::to_string(static_cast<uint8_t>(color.to4bits()) + 30) + "m";
126 if(color.getType() == Term::Color::Type::Bit4 || color.getType() == Term::Color::Type::Bit3) return "\u001b[" + std::to_string(static_cast<uint8_t>(color.to4bits()) + 30) + "m";
127 else
128 return "\u001b[38;5;" + std::to_string(color.to8bits()) + "m";
130 if(color.getType() == Term::Color::Type::Bit3 || color.getType() == Term::Color::Type::Bit4) return "\u001b[" + std::to_string(static_cast<uint8_t>(color.to4bits()) + 30) + "m";
131 else if(color.getType() == Term::Color::Type::Bit8)
132 return "\u001b[38;5;" + std::to_string(color.to8bits()) + "m";
133 else
134 return "\u001b[38;2;" + std::to_string(color.to24bits()[0]) + ';' + std::to_string(color.to24bits()[1]) + ';' + std::to_string(color.to24bits()[2]) + "m";
135 default: return {};
136 }
137}
Name to4bits() const
Definition color.cpp:48
std::uint8_t to8bits() const
Definition color.cpp:64
bool operator==(const Color &) const
Definition color.cpp:14
std::array< std::uint8_t, 3 > to24bits() const
Definition color.cpp:77
std::array< std::uint8_t, 3 > m_bit24
Definition color.hpp:77
Type getType() const
Definition color.cpp:37
std::uint8_t m_bit8
Definition color.hpp:76
Name to3bits() const
Definition color.cpp:39
Name
The 3bit/4bit colors for the terminal.
Definition color.hpp:40
@ Gray
Gray FG: 90, BG: 100.
bool operator!=(const Color &) const
Definition color.cpp:21
static ColorMode getColorMode()
Definition terminfo.cpp:136
std::string color_bg(const Term::Color::Name &name)
Definition color.cpp:79
std::string color_fg(const Term::Color::Name &name)
Definition color.cpp:110