Color.cpp 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. #include <AK/Assertions.h>
  2. #include <LibDraw/Color.h>
  3. #include <ctype.h>
  4. #include <stdio.h>
  5. Color::Color(NamedColor named)
  6. {
  7. struct {
  8. u8 r;
  9. u8 g;
  10. u8 b;
  11. } rgb;
  12. switch (named) {
  13. case Black:
  14. rgb = { 0, 0, 0 };
  15. break;
  16. case White:
  17. rgb = { 255, 255, 255 };
  18. break;
  19. case Red:
  20. rgb = { 255, 0, 0 };
  21. break;
  22. case Green:
  23. rgb = { 0, 255, 0 };
  24. break;
  25. case Cyan:
  26. rgb = { 0, 255, 255 };
  27. break;
  28. case DarkCyan:
  29. rgb = { 0, 127, 127 };
  30. break;
  31. case MidCyan:
  32. rgb = { 0, 192, 192 };
  33. break;
  34. case Blue:
  35. rgb = { 0, 0, 255 };
  36. break;
  37. case Yellow:
  38. rgb = { 255, 255, 0 };
  39. break;
  40. case Magenta:
  41. rgb = { 255, 0, 255 };
  42. break;
  43. case DarkGray:
  44. rgb = { 64, 64, 64 };
  45. break;
  46. case MidGray:
  47. rgb = { 127, 127, 127 };
  48. break;
  49. case LightGray:
  50. rgb = { 192, 192, 192 };
  51. break;
  52. case MidGreen:
  53. rgb = { 0, 192, 0 };
  54. break;
  55. case MidBlue:
  56. rgb = { 0, 0, 192 };
  57. break;
  58. case MidRed:
  59. rgb = { 192, 0, 0 };
  60. break;
  61. case MidMagenta:
  62. rgb = { 192, 0, 192 };
  63. break;
  64. case DarkGreen:
  65. rgb = { 0, 128, 0 };
  66. break;
  67. case DarkBlue:
  68. rgb = { 0, 0, 128 };
  69. break;
  70. case DarkRed:
  71. rgb = { 128, 0, 0 };
  72. break;
  73. case WarmGray:
  74. rgb = { 212, 208, 200 };
  75. break;
  76. default:
  77. ASSERT_NOT_REACHED();
  78. break;
  79. }
  80. m_value = 0xff000000 | (rgb.r << 16) | (rgb.g << 8) | rgb.b;
  81. }
  82. String Color::to_string() const
  83. {
  84. return String::format("#%b%b%b%b", red(), green(), blue(), alpha());
  85. }
  86. Optional<Color> Color::from_string(const StringView& string)
  87. {
  88. if (string.is_empty())
  89. return {};
  90. struct ColorAndWebName {
  91. RGBA32 color;
  92. const char* name;
  93. };
  94. const ColorAndWebName web_colors[] = {
  95. { 0x800000, "maroon", },
  96. { 0xff0000, "red", },
  97. { 0xffa500, "orange" },
  98. { 0xffff00, "yellow" },
  99. { 0x808000, "olive" },
  100. { 0x800080, "purple" },
  101. { 0xff00ff, "fuchsia" },
  102. { 0xffffff, "white" },
  103. { 0x00ff00, "lime" },
  104. { 0x008000, "green" },
  105. { 0x000080, "navy" },
  106. { 0x0000ff, "blue" },
  107. { 0x00ffff, "aqua" },
  108. { 0x008080, "teal" },
  109. { 0x000000, "black" },
  110. { 0xc0c0c0, "silver" },
  111. { 0x808080, "gray" },
  112. { 0xffc0cb, "pink" },
  113. { 0x000000, nullptr }
  114. };
  115. for (size_t i = 0; web_colors[i].name; ++i) {
  116. if (string == web_colors[i].name)
  117. return Color::from_rgb(web_colors[i].color);
  118. }
  119. if (string[0] != '#')
  120. return {};
  121. auto hex_nibble_to_u8 = [](char nibble) -> Optional<u8> {
  122. if (!isxdigit(nibble))
  123. return {};
  124. if (nibble >= '0' && nibble <= '9')
  125. return nibble - '0';
  126. return 10 + (tolower(nibble) - 'a');
  127. };
  128. if (string.length() == 4) {
  129. Optional<u8> r = hex_nibble_to_u8(string[1]);
  130. Optional<u8> g = hex_nibble_to_u8(string[2]);
  131. Optional<u8> b = hex_nibble_to_u8(string[3]);
  132. if (!r.has_value() || !g.has_value() || !b.has_value())
  133. return {};
  134. return Color(r.value() * 17, g.value() * 17, b.value() * 17);
  135. }
  136. if (string.length() != 7 && string.length() != 9)
  137. return {};
  138. auto to_hex = [&](char c1, char c2) -> Optional<u8> {
  139. auto nib1 = hex_nibble_to_u8(c1);
  140. auto nib2 = hex_nibble_to_u8(c2);
  141. if (!nib1.has_value() || !nib2.has_value())
  142. return {};
  143. return nib1.value() << 4 | nib2.value();
  144. };
  145. Optional<u8> r = to_hex(string[1], string[2]);
  146. Optional<u8> g = to_hex(string[3], string[4]);
  147. Optional<u8> b = to_hex(string[5], string[6]);
  148. Optional<u8> a = string.length() == 9 ? to_hex(string[7], string[8]) : Optional<u8>(255);
  149. if (!r.has_value() || !g.has_value() || !b.has_value() || !a.has_value())
  150. return {};
  151. return Color(r.value(), g.value(), b.value(), a.value());
  152. }