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