Color.h 2.9 KB

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