1 /*
2 SPDX-FileCopyrightText: 2007-2008 Robert Knight <robertknight@gmail.com>
3 SPDX-FileCopyrightText: 1997, 1998 Lars Doelle <lars.doelle@on-line.de>
4
5 SPDX-License-Identifier: GPL-2.0-or-later
6 */
7
8 #ifndef CHARACTERCOLOR_H
9 #define CHARACTERCOLOR_H
10
11 // Qt
12 #include <QColor>
13
14 namespace Konsole
15 {
16 // Attributed Character Representations ///////////////////////////////
17
18 // Colors
19
20 #define BASE_COLORS (2 + 8)
21 #define INTENSITIES 3
22 #define TABLE_COLORS (INTENSITIES * BASE_COLORS)
23
24 enum ColorTableIndex {
25 ColorFgIndex,
26 ColorBgIndex,
27 Color0Index,
28 Color1Index,
29 Color2Index,
30 Color3Index,
31 Color4Index,
32 Color5Index,
33 Color6Index,
34 Color7Index,
35
36 ColorFgIntenseIndex,
37 ColorBgIntenseIndex,
38 Color0IntenseIndex,
39 Color1IntenseIndex,
40 Color2IntenseIndex,
41 Color3IntenseIndex,
42 Color4IntenseIndex,
43 Color5IntenseIndex,
44 Color6IntenseIndex,
45 Color7IntenseIndex,
46
47 ColorFgFaintIndex,
48 ColorBgFaintIndex,
49 Color0FaintIndex,
50 Color1FaintIndex,
51 Color2FaintIndex,
52 Color3FaintIndex,
53 Color4FaintIndex,
54 Color5FaintIndex,
55 Color6FaintIndex,
56 Color7FaintIndex,
57 };
58
59 #define DEFAULT_FORE_COLOR 0
60 #define DEFAULT_BACK_COLOR 1
61
62 /* CharacterColor is a union of the various color spaces.
63
64 Assignment is as follows:
65
66 Type - Space - Values
67
68 0 - Undefined - u: 0, v:0 w:0
69 1 - Default - u: 0..1 v:intense w:0
70 2 - System - u: 0..7 v:intense w:0
71 3 - Index(256) - u: 16..255 v:0 w:0
72 4 - RGB - u: 0..255 v:0..256 w:0..256
73
74 ``intense'' is either 0 (normal), 1 (intensive), or 2 (faint)
75
76 Default color space has two separate colors, namely
77 default foreground and default background color.
78 */
79
80 #define COLOR_SPACE_UNDEFINED 0
81 #define COLOR_SPACE_DEFAULT 1
82 #define COLOR_SPACE_SYSTEM 2
83 #define COLOR_SPACE_256 3
84 #define COLOR_SPACE_RGB 4
85
86 /**
87 * Describes the color of a single character in the terminal.
88 */
89 class CharacterColor
90 {
91 friend class Character;
92
93 public:
94 /** Constructs a new CharacterColor whose color and color space are undefined. */
CharacterColor()95 CharacterColor()
96 : _colorSpace(COLOR_SPACE_UNDEFINED)
97 , _u(0)
98 , _v(0)
99 , _w(0)
100 {
101 }
102
103 /**
104 * Constructs a new CharacterColor using the specified @p colorSpace and with
105 * color value @p co
106 *
107 * The meaning of @p co depends on the @p colorSpace used.
108 *
109 * TODO : Document how @p co relates to @p colorSpace
110 *
111 * TODO : Add documentation about available color spaces.
112 */
CharacterColor(quint8 colorSpace,int co)113 CharacterColor(quint8 colorSpace, int co)
114 : _colorSpace(colorSpace)
115 , _u(0)
116 , _v(0)
117 , _w(0)
118 {
119 switch (colorSpace) {
120 case COLOR_SPACE_DEFAULT:
121 _u = co & 1;
122 break;
123 case COLOR_SPACE_SYSTEM:
124 _u = co & 7;
125 _v = (co >> 3) & 3;
126 break;
127 case COLOR_SPACE_256:
128 _u = co & 255;
129 break;
130 case COLOR_SPACE_RGB:
131 _u = co >> 16;
132 _v = co >> 8;
133 _w = co;
134 break;
135 default:
136 _colorSpace = COLOR_SPACE_UNDEFINED;
137 }
138 }
139
colorSpace()140 quint8 colorSpace() const
141 {
142 return _colorSpace;
143 }
termColor(int * u,int * v,int * w)144 void termColor(int *u, int *v, int *w)
145 {
146 *u = _u;
147 *v = _v;
148 *w = _w;
149 }
150
151 /**
152 * Returns true if this character color entry is valid.
153 */
isValid()154 bool isValid() const
155 {
156 return _colorSpace != COLOR_SPACE_UNDEFINED;
157 }
158
159 /**
160 * Set this color as an intensive system color.
161 *
162 * This is only applicable if the color is using the COLOR_SPACE_DEFAULT or COLOR_SPACE_SYSTEM
163 * color spaces.
164 */
165 void setIntensive();
166
167 /**
168 * Set this color as a faint system color.
169 *
170 * This is only applicable if the color is using the COLOR_SPACE_DEFAULT or COLOR_SPACE_SYSTEM
171 * color spaces.
172 */
173 void setFaint();
174
175 /**
176 * Returns the color within the specified color @p base
177 *
178 * The @p base is only used if this color is one of the 16 system colors, otherwise
179 * it is ignored.
180 */
181 QColor color(const QColor *base) const;
182
183 /**
184 * Compares two colors and returns true if they represent the same color value and
185 * use the same color space.
186 */
187 friend bool operator==(const CharacterColor &a, const CharacterColor &b);
188 /**
189 * Compares two colors and returns true if they represent different color values
190 * or use different color spaces.
191 */
192 friend bool operator!=(const CharacterColor &a, const CharacterColor &b);
193
194 private:
195 quint8 _colorSpace;
196
197 // bytes storing the character color
198 quint8 _u;
199 quint8 _v;
200 quint8 _w;
201 };
202
203 inline bool operator==(const CharacterColor &a, const CharacterColor &b)
204 {
205 return a._colorSpace == b._colorSpace && a._u == b._u && a._v == b._v && a._w == b._w;
206 }
207
208 inline bool operator!=(const CharacterColor &a, const CharacterColor &b)
209 {
210 return !operator==(a, b);
211 }
212
color256(quint8 u,const QColor * base)213 inline const QColor color256(quint8 u, const QColor *base)
214 {
215 // 0.. 16: system colors
216 if (u < 8) {
217 return base[u + 2];
218 }
219 u -= 8;
220 if (u < 8) {
221 return base[u + 2 + BASE_COLORS];
222 }
223 u -= 8;
224
225 // 16..231: 6x6x6 rgb color cube
226 if (u < 216) {
227 return QColor(((u / 36) % 6) ? (40 * ((u / 36) % 6) + 55) : 0,
228 ((u / 6) % 6) ? (40 * ((u / 6) % 6) + 55) : 0,
229 ((u / 1) % 6) ? (40 * ((u / 1) % 6) + 55) : 0);
230 }
231 u -= 216;
232
233 // 232..255: gray, leaving out black and white
234 int gray = u * 10 + 8;
235
236 return QColor(gray, gray, gray);
237 }
238
color(const QColor * base)239 inline QColor CharacterColor::color(const QColor *base) const
240 {
241 switch (_colorSpace) {
242 case COLOR_SPACE_DEFAULT:
243 return base[_u + 0 + (_v * BASE_COLORS)];
244 case COLOR_SPACE_SYSTEM:
245 return base[_u + 2 + (_v * BASE_COLORS)];
246 case COLOR_SPACE_256:
247 return color256(_u, base);
248 case COLOR_SPACE_RGB:
249 return QColor(_u, _v, _w);
250 case COLOR_SPACE_UNDEFINED:
251 return QColor();
252 }
253
254 Q_ASSERT(false); // invalid color space
255
256 return QColor();
257 }
258
setIntensive()259 inline void CharacterColor::setIntensive()
260 {
261 if (_colorSpace == COLOR_SPACE_SYSTEM || _colorSpace == COLOR_SPACE_DEFAULT) {
262 _v = 1;
263 }
264 }
265
setFaint()266 inline void CharacterColor::setFaint()
267 {
268 if (_colorSpace == COLOR_SPACE_SYSTEM || _colorSpace == COLOR_SPACE_DEFAULT) {
269 _v = 2;
270 }
271 }
272 }
273
274 #endif // CHARACTERCOLOR_H
275