Serenity Operating System
at master 153 lines 2.9 kB view raw
1/* 2 * Copyright (c) 2021, Daniel Bertalan <dani@danielbertalan.dev> 3 * 4 * SPDX-License-Identifier: BSD-2-Clause 5 */ 6 7#pragma once 8 9#include <AK/Types.h> 10 11namespace VT { 12 13class Color { 14public: 15 enum class ANSIColor : u16 { 16 Black = 0, 17 Red, 18 Green, 19 Yellow, 20 Blue, 21 Magenta, 22 Cyan, 23 White, 24 BrightBlack, 25 BrightRed, 26 BrightGreen, 27 BrightYellow, 28 BrightBlue, 29 BrightMagenta, 30 BrightCyan, 31 BrightWhite, 32 // We use the values above to directly index into the color lookup table, 33 // but the ones below are handled separately. 34 DefaultForeground = 256, 35 DefaultBackground 36 }; 37 38 static constexpr Color rgb(u32 rgb) 39 { 40 return Color(rgb); 41 } 42 43 static constexpr Color indexed(u8 index) 44 { 45 return Color(index); 46 } 47 48 static constexpr Color named(ANSIColor name) 49 { 50 return Color(name); 51 } 52 53 constexpr bool is_rgb() const 54 { 55 return m_kind == Kind::RGB; 56 } 57 58 constexpr bool is_indexed() const 59 { 60 return m_kind == Kind::Indexed; 61 } 62 63 constexpr bool is_named() const 64 { 65 return m_kind == Kind::Named; 66 } 67 68 constexpr u32 as_rgb() const 69 { 70 VERIFY(is_rgb()); 71 return m_value.as_rgb; 72 } 73 74 constexpr u8 as_indexed() const 75 { 76 VERIFY(is_indexed()); 77 return m_value.as_indexed; 78 } 79 80 constexpr ANSIColor as_named() const 81 { 82 VERIFY(is_named()); 83 return m_value.as_named; 84 } 85 86 constexpr Color to_bright() const 87 { 88 if (is_named()) { 89 auto numeric_value = static_cast<u16>(as_named()); 90 if (numeric_value < 8) 91 return Color::named(static_cast<ANSIColor>(numeric_value + 8)); 92 return *this; 93 } else { 94 return *this; 95 } 96 } 97 98 constexpr bool operator==(Color const& other) const 99 { 100 if (m_kind != other.kind()) 101 return false; 102 103 switch (m_kind) { 104 case RGB: 105 return m_value.as_rgb == other.as_rgb(); 106 case Indexed: 107 return m_value.as_indexed == other.as_indexed(); 108 case Named: 109 return m_value.as_named == other.as_named(); 110 default: 111 VERIFY_NOT_REACHED(); 112 }; 113 } 114 115 enum Kind { 116 RGB, 117 Indexed, 118 Named 119 }; 120 121 constexpr Kind kind() const 122 { 123 return m_kind; 124 } 125 126private: 127 Kind m_kind; 128 129 union { 130 u32 as_rgb; 131 u8 as_indexed; 132 ANSIColor as_named; 133 } m_value; 134 135 constexpr Color(u32 rgb) 136 : m_kind(Kind::RGB) 137 { 138 m_value.as_rgb = rgb; 139 } 140 141 constexpr Color(u8 index) 142 : m_kind(Kind::Indexed) 143 { 144 m_value.as_indexed = index; 145 } 146 147 constexpr Color(ANSIColor name) 148 : m_kind(Kind::Named) 149 { 150 m_value.as_named = name; 151 } 152}; 153}