1 /*
2 This file is part of Konsole, KDE's terminal.
3
4 Copyright (C) 2007, 2013 by Robert Knight <robertknight@gmail.com>
5 Copyright (C) 1997,1998 by Lars Doelle <lars.doelle@on-line.de>
6
7 Rewritten for QT4 by e_k <e_k at users.sourceforge.net>, Copyright (C)2008
8
9 This program is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22 02110-1301 USA.
23 */
24
25 #ifndef CHARACTERCOLOR_H
26 #define CHARACTERCOLOR_H
27
28 // Qt
29 #include <QColor>
30
31 /**
32 * An entry in a terminal display's color palette.
33 *
34 * A color palette is an array of 16 ColorEntry instances which map
35 * system color indexes (from 0 to 15) into actual colors.
36 *
37 * Each entry can be set as bold, in which case any text
38 * drawn using the color should be drawn in bold.
39 *
40 * Each entry can also be transparent, in which case the terminal
41 * display should avoid drawing the background for any characters
42 * using the entry as a background.
43 */
44 class ColorEntry
45 {
46 public:
47 /**
48 * Constructs a new color palette entry.
49 *
50 * @param c The color value for this entry.
51 * @param tr Specifies that the color should be transparent when used as a background color.
52 * @param b Specifies that text drawn with this color should be bold.
53 */
ColorEntry(QColor c,bool tr,bool b)54 ColorEntry(QColor c, bool tr, bool b) : color(c), transparent(tr), bold(b) {}
55
56 /**
57 * Constructs a new color palette entry with an undefined color, and
58 * with the transparent and bold flags set to false.
59 */
ColorEntry()60 ColorEntry() : transparent(false), bold(false) {}
61
62 /**
63 * Sets the color, transparency and boldness of this color to those of @p rhs.
64 */
65 void operator=(const ColorEntry& rhs)
66 {
67 color = rhs.color;
68 transparent = rhs.transparent;
69 bold = rhs.bold;
70 }
71
72 /** The color value of this entry for display. */
73 QColor color;
74
75 /**
76 * If true character backgrounds using this color should be transparent.
77 * This is not applicable when the color is used to render text.
78 */
79 bool transparent;
80 /**
81 * If true characters drawn using this color should be bold.
82 * This is not applicable when the color is used to draw a character's background.
83 */
84 bool bold;
85 };
86
87
88 // Attributed Character Representations ///////////////////////////////
89
90 // Colors
91
92 #define BASE_COLORS (2+8)
93 #define INTENSITIES 2
94 #define TABLE_COLORS (INTENSITIES*BASE_COLORS)
95
96 #define DEFAULT_FORE_COLOR 0
97 #define DEFAULT_BACK_COLOR 1
98
99 //a standard set of colors using black text on a white background.
100 //defined in TerminalDisplay.cpp
101
102 static const ColorEntry base_color_table[TABLE_COLORS] =
103 {
104 // normal
105 ColorEntry(QColor(0x00,0x00,0x00), 1, 0 ), ColorEntry( QColor(0xFF,0xFF,0xFF), 0, 0 ), // Dfore, Dback
106 ColorEntry(QColor(0x00,0x00,0x00), 0, 0 ), ColorEntry( QColor(0xB2,0x18,0x18), 0, 0 ), // Black, Red
107 ColorEntry(QColor(0x18,0xB2,0x18), 0, 0 ), ColorEntry( QColor(0xB2,0x68,0x18), 0, 0 ), // Green, Yellow
108 ColorEntry(QColor(0x18,0x18,0xB2), 0, 0 ), ColorEntry( QColor(0xB2,0x18,0xB2), 0, 0 ), // Blue, Magenta
109 ColorEntry(QColor(0x18,0xB2,0xB2), 0, 0 ), ColorEntry( QColor(0xB2,0xB2,0xB2), 0, 0 ), // Cyan, White
110 // intensiv
111 ColorEntry(QColor(0x00,0x00,0x00), 0, 1 ), ColorEntry( QColor(0xFF,0xFF,0xFF), 1, 0 ),
112 ColorEntry(QColor(0x68,0x68,0x68), 0, 0 ), ColorEntry( QColor(0xFF,0x54,0x54), 0, 0 ),
113 ColorEntry(QColor(0x54,0xFF,0x54), 0, 0 ), ColorEntry( QColor(0xFF,0xFF,0x54), 0, 0 ),
114 ColorEntry(QColor(0x54,0x54,0xFF), 0, 0 ), ColorEntry( QColor(0xFF,0x54,0xFF), 0, 0 ),
115 ColorEntry(QColor(0x54,0xFF,0xFF), 0, 0 ), ColorEntry( QColor(0xFF,0xFF,0xFF), 0, 0 )
116 };
117
118 /* CharacterColor is a union of the various color spaces.
119
120 Assignment is as follows:
121
122 Type - Space - Values
123
124 0 - Undefined - u: 0, v:0 w:0
125 1 - Default - u: 0..1 v:intense w:0
126 2 - System - u: 0..7 v:intense w:0
127 3 - Index(256) - u: 16..255 v:0 w:0
128 4 - RGB - u: 0..255 v:0..256 w:0..256
129
130 Default colour space has two separate colours, namely
131 default foreground and default background colour.
132 */
133
134 #define COLOR_SPACE_UNDEFINED 0
135 #define COLOR_SPACE_DEFAULT 1
136 #define COLOR_SPACE_SYSTEM 2
137 #define COLOR_SPACE_256 3
138 #define COLOR_SPACE_RGB 4
139
140 /**
141 * Describes the color of a single character in the terminal.
142 */
143 class CharacterColor
144 {
145 friend class Character;
146
147 public:
148 /** Constructs a new CharacterColor whoose color and color space are undefined. */
CharacterColor()149 CharacterColor()
150 : _colorSpace(COLOR_SPACE_UNDEFINED),
151 _u(0),
152 _v(0),
153 _w(0)
154 {}
155
156 /**
157 * Constructs a new CharacterColor using the specified @p colorSpace and with
158 * color value @p co
159 *
160 * The meaning of @p co depends on the @p colorSpace used.
161 *
162 * TODO : Document how @p co relates to @p colorSpace
163 *
164 * TODO : Add documentation about available color spaces.
165 */
CharacterColor(quint8 colorSpace,int co)166 CharacterColor(quint8 colorSpace, int co)
167 : _colorSpace(colorSpace),
168 _u(0),
169 _v(0),
170 _w(0)
171 {
172 switch (colorSpace)
173 {
174 case COLOR_SPACE_DEFAULT:
175 _u = co & 1;
176 break;
177 case COLOR_SPACE_SYSTEM:
178 _u = co & 7;
179 _v = (co >> 3) & 1;
180 break;
181 case COLOR_SPACE_256:
182 _u = co & 255;
183 break;
184 case COLOR_SPACE_RGB:
185 _u = co >> 16;
186 _v = co >> 8;
187 _w = co;
188 break;
189 default:
190 _colorSpace = COLOR_SPACE_UNDEFINED;
191 }
192 }
193
194 /**
195 * Returns true if this character color entry is valid.
196 */
isValid()197 bool isValid()
198 {
199 return _colorSpace != COLOR_SPACE_UNDEFINED;
200 }
201
202 /**
203 * Toggles the value of this color between a normal system color and the corresponding intensive
204 * system color.
205 *
206 * This is only applicable if the color is using the COLOR_SPACE_DEFAULT or COLOR_SPACE_SYSTEM
207 * color spaces.
208 */
209 void toggleIntensive();
210
211 /**
212 * Returns the color within the specified color @palette
213 *
214 * The @p palette is only used if this color is one of the 16 system colors, otherwise
215 * it is ignored.
216 */
217 QColor color(const ColorEntry* palette) const;
218
219 /**
220 * Compares two colors and returns true if they represent the same color value and
221 * use the same color space.
222 */
223 friend bool operator == (const CharacterColor& a, const CharacterColor& b);
224 /**
225 * Compares two colors and returns true if they represent different color values
226 * or use different color spaces.
227 */
228 friend bool operator != (const CharacterColor& a, const CharacterColor& b);
229
230 private:
231 quint8 _colorSpace;
232
233 // bytes storing the character color
234 quint8 _u;
235 quint8 _v;
236 quint8 _w;
237 };
238
239 inline bool operator == (const CharacterColor& a, const CharacterColor& b)
240 {
241 return a._colorSpace == b._colorSpace &&
242 a._u == b._u &&
243 a._v == b._v &&
244 a._w == b._w;
245 }
246
247 inline bool operator != (const CharacterColor& a, const CharacterColor& b)
248 {
249 return !operator==(a,b);
250 }
251
color256(quint8 u,const ColorEntry * base)252 inline const QColor color256(quint8 u, const ColorEntry* base)
253 {
254 // 0.. 16: system colors
255 if (u < 8) return base[u+2 ].color; u -= 8;
256 if (u < 8) return base[u+2+BASE_COLORS].color; u -= 8;
257
258 // 16..231: 6x6x6 rgb color cube
259 if (u < 216) return QColor(255*((u/36)%6)/5,
260 255*((u/ 6)%6)/5,
261 255*((u/ 1)%6)/5); u -= 216;
262
263 // 232..255: gray, leaving out black and white
264 int gray = u*10+8; return QColor(gray,gray,gray);
265 }
266
color(const ColorEntry * base)267 inline QColor CharacterColor::color(const ColorEntry* base) const
268 {
269 switch (_colorSpace)
270 {
271 case COLOR_SPACE_DEFAULT: return base[_u+0+(_v?BASE_COLORS:0)].color;
272 case COLOR_SPACE_SYSTEM: return base[_u+2+(_v?BASE_COLORS:0)].color;
273 case COLOR_SPACE_256: return color256(_u,base);
274 case COLOR_SPACE_RGB: return QColor(_u,_v,_w);
275 case COLOR_SPACE_UNDEFINED: return QColor();
276 }
277
278 Q_ASSERT(false); // invalid color space
279
280 return QColor();
281 }
282
toggleIntensive()283 inline void CharacterColor::toggleIntensive()
284 {
285 if (_colorSpace == COLOR_SPACE_SYSTEM || _colorSpace == COLOR_SPACE_DEFAULT)
286 {
287 _v = !_v;
288 }
289 }
290
291 #endif // CHARACTERCOLOR_H
292