File indexing completed on 2024-05-05 05:53:43

0001 /*
0002     SPDX-FileCopyrightText: 2007-2008 Robert Knight <robertknight@gmail.com>
0003     SPDX-FileCopyrightText: 1997, 1998 Lars Doelle <lars.doelle@on-line.de>
0004 
0005     SPDX-License-Identifier: GPL-2.0-or-later
0006 */
0007 
0008 #ifndef CHARACTERCOLOR_H
0009 #define CHARACTERCOLOR_H
0010 
0011 // Qt
0012 #include <QColor>
0013 
0014 namespace Konsole
0015 {
0016 // Attributed Character Representations ///////////////////////////////
0017 
0018 // Colors
0019 
0020 #define BASE_COLORS (2 + 8)
0021 #define INTENSITIES 3
0022 #define TABLE_COLORS (INTENSITIES * BASE_COLORS)
0023 
0024 enum ColorTableIndex {
0025     ColorFgIndex,
0026     ColorBgIndex,
0027     Color0Index,
0028     Color1Index,
0029     Color2Index,
0030     Color3Index,
0031     Color4Index,
0032     Color5Index,
0033     Color6Index,
0034     Color7Index,
0035 
0036     ColorFgIntenseIndex,
0037     ColorBgIntenseIndex,
0038     Color0IntenseIndex,
0039     Color1IntenseIndex,
0040     Color2IntenseIndex,
0041     Color3IntenseIndex,
0042     Color4IntenseIndex,
0043     Color5IntenseIndex,
0044     Color6IntenseIndex,
0045     Color7IntenseIndex,
0046 
0047     ColorFgFaintIndex,
0048     ColorBgFaintIndex,
0049     Color0FaintIndex,
0050     Color1FaintIndex,
0051     Color2FaintIndex,
0052     Color3FaintIndex,
0053     Color4FaintIndex,
0054     Color5FaintIndex,
0055     Color6FaintIndex,
0056     Color7FaintIndex,
0057 };
0058 
0059 #define DEFAULT_FORE_COLOR 0
0060 #define DEFAULT_BACK_COLOR 1
0061 
0062 /* CharacterColor is a union of the various color spaces.
0063 
0064    Assignment is as follows:
0065 
0066    Type  - Space        - Values
0067 
0068    0     - Undefined   - u:  0,      v:0        w:0
0069    1     - Default     - u:  0..1    v:intense  w:0
0070    2     - System      - u:  0..7    v:intense  w:0
0071    3     - Index(256)  - u: 16..255  v:0        w:0
0072    4     - RGB         - u:  0..255  v:0..256   w:0..256
0073 
0074    ``intense'' is either 0 (normal), 1 (intensive), or 2 (faint)
0075 
0076    Default color space has two separate colors, namely
0077    default foreground and default background color.
0078 */
0079 
0080 #define COLOR_SPACE_UNDEFINED 0
0081 #define COLOR_SPACE_DEFAULT 1
0082 #define COLOR_SPACE_SYSTEM 2
0083 #define COLOR_SPACE_256 3
0084 #define COLOR_SPACE_RGB 4
0085 
0086 /**
0087  * Describes the color of a single character in the terminal.
0088  */
0089 class CharacterColor
0090 {
0091     friend class Character;
0092 
0093 public:
0094     /** Constructs a new CharacterColor whose color and color space are undefined. */
0095     constexpr CharacterColor()
0096         : _colorSpace(COLOR_SPACE_UNDEFINED)
0097         , _u(0)
0098         , _v(0)
0099         , _w(0)
0100     {
0101     }
0102 
0103     /**
0104      * Constructs a new CharacterColor using the specified @p colorSpace and with
0105      * color value @p co
0106      *
0107      * The meaning of @p co depends on the @p colorSpace used.
0108      *
0109      * TODO : Document how @p co relates to @p colorSpace
0110      *
0111      * TODO : Add documentation about available color spaces.
0112      */
0113     constexpr CharacterColor(quint8 colorSpace, int co)
0114         : _colorSpace(colorSpace)
0115         , _u(0)
0116         , _v(0)
0117         , _w(0)
0118     {
0119         switch (colorSpace) {
0120         case COLOR_SPACE_DEFAULT:
0121             _u = co & 1;
0122             break;
0123         case COLOR_SPACE_SYSTEM:
0124             _u = co & 7;
0125             _v = (co >> 3) & 3;
0126             break;
0127         case COLOR_SPACE_256:
0128             _u = co & 255;
0129             break;
0130         case COLOR_SPACE_RGB:
0131             _u = co >> 16;
0132             _v = co >> 8;
0133             _w = co;
0134             break;
0135         default:
0136             _colorSpace = COLOR_SPACE_UNDEFINED;
0137         }
0138     }
0139 
0140     constexpr quint8 colorSpace() const
0141     {
0142         return _colorSpace;
0143     }
0144     constexpr void termColor(int *u, int *v, int *w)
0145     {
0146         *u = _u;
0147         *v = _v;
0148         *w = _w;
0149     }
0150 
0151     /**
0152      * Returns true if this character color entry is valid.
0153      */
0154     constexpr bool isValid() const
0155     {
0156         return _colorSpace != COLOR_SPACE_UNDEFINED;
0157     }
0158 
0159     /**
0160      * Set this color as an intensive system color.
0161      *
0162      * This is only applicable if the color is using the COLOR_SPACE_DEFAULT or COLOR_SPACE_SYSTEM
0163      * color spaces.
0164      */
0165     void setIntensive();
0166 
0167     /**
0168      * Set this color as a faint system color.
0169      *
0170      * This is only applicable if the color is using the COLOR_SPACE_DEFAULT or COLOR_SPACE_SYSTEM
0171      * color spaces.
0172      */
0173     void setFaint();
0174 
0175     /**
0176      * Returns the color within the specified color @p base
0177      *
0178      * The @p base is only used if this color is one of the 16 system colors, otherwise
0179      * it is ignored.
0180      */
0181     constexpr QColor color(const QColor *base) const;
0182 
0183     /**
0184      * Compares two colors and returns true if they represent the same color value and
0185      * use the same color space.
0186      */
0187     friend constexpr bool operator==(const CharacterColor a, const CharacterColor b)
0188     {
0189         return std::tie(a._colorSpace, a._u, a._v, a._w) == std::tie(b._colorSpace, b._u, b._v, b._w);
0190     }
0191     /**
0192      * Compares two colors and returns true if they represent different color values
0193      * or use different color spaces.
0194      */
0195     friend constexpr bool operator!=(const CharacterColor a, const CharacterColor b)
0196     {
0197         return !operator==(a, b);
0198     }
0199 
0200 private:
0201     quint8 _colorSpace;
0202 
0203     // bytes storing the character color
0204     quint8 _u;
0205     quint8 _v;
0206     quint8 _w;
0207 };
0208 
0209 constexpr QColor color256(quint8 u, const QColor *base)
0210 {
0211     //   0.. 16: system colors
0212     if (u < 8) {
0213         return base[u + 2];
0214     }
0215     u -= 8;
0216     if (u < 8) {
0217         return base[u + 2 + BASE_COLORS];
0218     }
0219     u -= 8;
0220 
0221     //  16..231: 6x6x6 rgb color cube
0222     if (u < 216) {
0223         return QColor(((u / 36) % 6) ? (40 * ((u / 36) % 6) + 55) : 0,
0224                       ((u / 6) % 6) ? (40 * ((u / 6) % 6) + 55) : 0,
0225                       ((u / 1) % 6) ? (40 * ((u / 1) % 6) + 55) : 0);
0226     }
0227     u -= 216;
0228 
0229     // 232..255: gray, leaving out black and white
0230     int gray = u * 10 + 8;
0231 
0232     return QColor(gray, gray, gray);
0233 }
0234 
0235 constexpr QColor CharacterColor::color(const QColor *base) const
0236 {
0237     switch (_colorSpace) {
0238     case COLOR_SPACE_DEFAULT:
0239         return base[_u + 0 + (_v * BASE_COLORS)];
0240     case COLOR_SPACE_SYSTEM:
0241         return base[_u + 2 + (_v * BASE_COLORS)];
0242     case COLOR_SPACE_256:
0243         return color256(_u, base);
0244     case COLOR_SPACE_RGB:
0245         return QColor(_u, _v, _w);
0246     case COLOR_SPACE_UNDEFINED:
0247         return QColor();
0248     }
0249 
0250     Q_ASSERT(false); // invalid color space
0251 
0252     return QColor();
0253 }
0254 
0255 inline void CharacterColor::setIntensive()
0256 {
0257     if (_colorSpace == COLOR_SPACE_SYSTEM || _colorSpace == COLOR_SPACE_DEFAULT) {
0258         _v = 1;
0259     }
0260 }
0261 
0262 inline void CharacterColor::setFaint()
0263 {
0264     if (_colorSpace == COLOR_SPACE_SYSTEM || _colorSpace == COLOR_SPACE_DEFAULT) {
0265         _v = 2;
0266     }
0267 }
0268 }
0269 
0270 #endif // CHARACTERCOLOR_H