Color.h 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424
  1. /*
  2. * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #pragma once
  7. #include <AK/Assertions.h>
  8. #include <AK/Format.h>
  9. #include <AK/Forward.h>
  10. #include <AK/SIMD.h>
  11. #include <AK/StdLibExtras.h>
  12. #include <LibIPC/Forward.h>
  13. #include <math.h>
  14. namespace Gfx {
  15. enum class ColorRole;
  16. typedef u32 RGBA32;
  17. constexpr u32 make_rgb(u8 r, u8 g, u8 b)
  18. {
  19. return ((r << 16) | (g << 8) | b);
  20. }
  21. struct HSV {
  22. double hue { 0 };
  23. double saturation { 0 };
  24. double value { 0 };
  25. };
  26. class Color {
  27. public:
  28. enum NamedColor {
  29. Transparent,
  30. Black,
  31. White,
  32. Red,
  33. Green,
  34. Cyan,
  35. Blue,
  36. Yellow,
  37. Magenta,
  38. DarkGray,
  39. MidGray,
  40. LightGray,
  41. WarmGray,
  42. DarkCyan,
  43. DarkGreen,
  44. DarkBlue,
  45. DarkRed,
  46. MidCyan,
  47. MidGreen,
  48. MidRed,
  49. MidBlue,
  50. MidMagenta,
  51. };
  52. constexpr Color() { }
  53. constexpr Color(NamedColor);
  54. constexpr Color(u8 r, u8 g, u8 b)
  55. : m_value(0xff000000 | (r << 16) | (g << 8) | b)
  56. {
  57. }
  58. constexpr Color(u8 r, u8 g, u8 b, u8 a)
  59. : m_value((a << 24) | (r << 16) | (g << 8) | b)
  60. {
  61. }
  62. static constexpr Color from_rgb(unsigned rgb) { return Color(rgb | 0xff000000); }
  63. static constexpr Color from_rgba(unsigned rgba) { return Color(rgba); }
  64. static constexpr Color from_cmyk(float c, float m, float y, float k)
  65. {
  66. auto r = static_cast<u8>(255.0f * (1.0f - c) * (1.0f - k));
  67. auto g = static_cast<u8>(255.0f * (1.0f - m) * (1.0f - k));
  68. auto b = static_cast<u8>(255.0f * (1.0f - y) * (1.0f - k));
  69. return Color(r, g, b);
  70. }
  71. constexpr u8 red() const { return (m_value >> 16) & 0xff; }
  72. constexpr u8 green() const { return (m_value >> 8) & 0xff; }
  73. constexpr u8 blue() const { return m_value & 0xff; }
  74. constexpr u8 alpha() const { return (m_value >> 24) & 0xff; }
  75. void set_alpha(u8 value)
  76. {
  77. m_value &= 0x00ffffff;
  78. m_value |= value << 24;
  79. }
  80. constexpr void set_red(u8 value)
  81. {
  82. m_value &= 0xff00ffff;
  83. m_value |= value << 16;
  84. }
  85. constexpr void set_green(u8 value)
  86. {
  87. m_value &= 0xffff00ff;
  88. m_value |= value << 8;
  89. }
  90. constexpr void set_blue(u8 value)
  91. {
  92. m_value &= 0xffffff00;
  93. m_value |= value;
  94. }
  95. constexpr Color with_alpha(u8 alpha) const
  96. {
  97. return Color((m_value & 0x00ffffff) | alpha << 24);
  98. }
  99. constexpr Color blend(Color source) const
  100. {
  101. if (!alpha() || source.alpha() == 255)
  102. return source;
  103. if (!source.alpha())
  104. return *this;
  105. #ifdef __SSE__
  106. using AK::SIMD::i32x4;
  107. const i32x4 color = {
  108. red(),
  109. green(),
  110. blue()
  111. };
  112. const i32x4 source_color = {
  113. source.red(),
  114. source.green(),
  115. source.blue()
  116. };
  117. const int d = 255 * (alpha() + source.alpha()) - alpha() * source.alpha();
  118. const i32x4 out = (color * alpha() * (255 - source.alpha()) + 255 * source.alpha() * source_color) / d;
  119. return Color(out[0], out[1], out[2], d / 255);
  120. #else
  121. int d = 255 * (alpha() + source.alpha()) - alpha() * source.alpha();
  122. u8 r = (red() * alpha() * (255 - source.alpha()) + 255 * source.alpha() * source.red()) / d;
  123. u8 g = (green() * alpha() * (255 - source.alpha()) + 255 * source.alpha() * source.green()) / d;
  124. u8 b = (blue() * alpha() * (255 - source.alpha()) + 255 * source.alpha() * source.blue()) / d;
  125. u8 a = d / 255;
  126. return Color(r, g, b, a);
  127. #endif
  128. }
  129. Color interpolate(const Color& other, float weight) const noexcept
  130. {
  131. u8 r = red() + roundf(static_cast<float>(other.red() - red()) * weight);
  132. u8 g = green() + roundf(static_cast<float>(other.green() - green()) * weight);
  133. u8 b = blue() + roundf(static_cast<float>(other.blue() - blue()) * weight);
  134. u8 a = alpha() + roundf(static_cast<float>(other.alpha() - alpha()) * weight);
  135. return Color(r, g, b, a);
  136. }
  137. constexpr Color multiply(const Color& other) const
  138. {
  139. return Color(
  140. red() * other.red() / 255,
  141. green() * other.green() / 255,
  142. blue() * other.blue() / 255,
  143. alpha() * other.alpha() / 255);
  144. }
  145. constexpr Color to_grayscale() const
  146. {
  147. int gray = (red() + green() + blue()) / 3;
  148. return Color(gray, gray, gray, alpha());
  149. }
  150. constexpr Color darkened(float amount = 0.5f) const
  151. {
  152. return Color(red() * amount, green() * amount, blue() * amount, alpha());
  153. }
  154. constexpr Color lightened(float amount = 1.2f) const
  155. {
  156. return Color(min(255, (int)((float)red() * amount)), min(255, (int)((float)green() * amount)), min(255, (int)((float)blue() * amount)), alpha());
  157. }
  158. constexpr Color inverted() const
  159. {
  160. return Color(~red(), ~green(), ~blue(), alpha());
  161. }
  162. constexpr Color xored(const Color& other) const
  163. {
  164. return Color(((other.m_value ^ m_value) & 0x00ffffff) | (m_value & 0xff000000));
  165. }
  166. constexpr RGBA32 value() const { return m_value; }
  167. constexpr bool operator==(const Color& other) const
  168. {
  169. return m_value == other.m_value;
  170. }
  171. constexpr bool operator!=(const Color& other) const
  172. {
  173. return m_value != other.m_value;
  174. }
  175. String to_string() const;
  176. String to_string_without_alpha() const;
  177. static Optional<Color> from_string(const StringView&);
  178. constexpr HSV to_hsv() const
  179. {
  180. HSV hsv;
  181. double r = static_cast<double>(red()) / 255.0;
  182. double g = static_cast<double>(green()) / 255.0;
  183. double b = static_cast<double>(blue()) / 255.0;
  184. double max = AK::max(AK::max(r, g), b);
  185. double min = AK::min(AK::min(r, g), b);
  186. double chroma = max - min;
  187. if (!chroma)
  188. hsv.hue = 0.0;
  189. else if (max == r)
  190. hsv.hue = (60.0 * ((g - b) / chroma)) + 360.0;
  191. else if (max == g)
  192. hsv.hue = (60.0 * ((b - r) / chroma)) + 120.0;
  193. else
  194. hsv.hue = (60.0 * ((r - g) / chroma)) + 240.0;
  195. if (hsv.hue >= 360.0)
  196. hsv.hue -= 360.0;
  197. if (!max)
  198. hsv.saturation = 0;
  199. else
  200. hsv.saturation = chroma / max;
  201. hsv.value = max;
  202. VERIFY(hsv.hue >= 0.0 && hsv.hue < 360.0);
  203. VERIFY(hsv.saturation >= 0.0 && hsv.saturation <= 1.0);
  204. VERIFY(hsv.value >= 0.0 && hsv.value <= 1.0);
  205. return hsv;
  206. }
  207. static constexpr Color from_hsv(double hue, double saturation, double value)
  208. {
  209. return from_hsv({ hue, saturation, value });
  210. }
  211. static constexpr Color from_hsv(const HSV& hsv)
  212. {
  213. VERIFY(hsv.hue >= 0.0 && hsv.hue < 360.0);
  214. VERIFY(hsv.saturation >= 0.0 && hsv.saturation <= 1.0);
  215. VERIFY(hsv.value >= 0.0 && hsv.value <= 1.0);
  216. double hue = hsv.hue;
  217. double saturation = hsv.saturation;
  218. double value = hsv.value;
  219. int high = static_cast<int>(hue / 60.0) % 6;
  220. double f = (hue / 60.0) - high;
  221. double c1 = value * (1.0 - saturation);
  222. double c2 = value * (1.0 - saturation * f);
  223. double c3 = value * (1.0 - saturation * (1.0 - f));
  224. double r = 0;
  225. double g = 0;
  226. double b = 0;
  227. switch (high) {
  228. case 0:
  229. r = value;
  230. g = c3;
  231. b = c1;
  232. break;
  233. case 1:
  234. r = c2;
  235. g = value;
  236. b = c1;
  237. break;
  238. case 2:
  239. r = c1;
  240. g = value;
  241. b = c3;
  242. break;
  243. case 3:
  244. r = c1;
  245. g = c2;
  246. b = value;
  247. break;
  248. case 4:
  249. r = c3;
  250. g = c1;
  251. b = value;
  252. break;
  253. case 5:
  254. r = value;
  255. g = c1;
  256. b = c2;
  257. break;
  258. }
  259. u8 out_r = (u8)(r * 255);
  260. u8 out_g = (u8)(g * 255);
  261. u8 out_b = (u8)(b * 255);
  262. return Color(out_r, out_g, out_b);
  263. }
  264. private:
  265. constexpr explicit Color(RGBA32 rgba)
  266. : m_value(rgba)
  267. {
  268. }
  269. RGBA32 m_value { 0 };
  270. };
  271. constexpr Color::Color(NamedColor named)
  272. {
  273. if (named == Transparent) {
  274. m_value = 0;
  275. return;
  276. }
  277. struct {
  278. u8 r;
  279. u8 g;
  280. u8 b;
  281. } rgb;
  282. switch (named) {
  283. case Black:
  284. rgb = { 0, 0, 0 };
  285. break;
  286. case White:
  287. rgb = { 255, 255, 255 };
  288. break;
  289. case Red:
  290. rgb = { 255, 0, 0 };
  291. break;
  292. case Green:
  293. rgb = { 0, 255, 0 };
  294. break;
  295. case Cyan:
  296. rgb = { 0, 255, 255 };
  297. break;
  298. case DarkCyan:
  299. rgb = { 0, 127, 127 };
  300. break;
  301. case MidCyan:
  302. rgb = { 0, 192, 192 };
  303. break;
  304. case Blue:
  305. rgb = { 0, 0, 255 };
  306. break;
  307. case Yellow:
  308. rgb = { 255, 255, 0 };
  309. break;
  310. case Magenta:
  311. rgb = { 255, 0, 255 };
  312. break;
  313. case DarkGray:
  314. rgb = { 64, 64, 64 };
  315. break;
  316. case MidGray:
  317. rgb = { 127, 127, 127 };
  318. break;
  319. case LightGray:
  320. rgb = { 192, 192, 192 };
  321. break;
  322. case MidGreen:
  323. rgb = { 0, 192, 0 };
  324. break;
  325. case MidBlue:
  326. rgb = { 0, 0, 192 };
  327. break;
  328. case MidRed:
  329. rgb = { 192, 0, 0 };
  330. break;
  331. case MidMagenta:
  332. rgb = { 192, 0, 192 };
  333. break;
  334. case DarkGreen:
  335. rgb = { 0, 128, 0 };
  336. break;
  337. case DarkBlue:
  338. rgb = { 0, 0, 128 };
  339. break;
  340. case DarkRed:
  341. rgb = { 128, 0, 0 };
  342. break;
  343. case WarmGray:
  344. rgb = { 212, 208, 200 };
  345. break;
  346. default:
  347. VERIFY_NOT_REACHED();
  348. break;
  349. }
  350. m_value = 0xff000000 | (rgb.r << 16) | (rgb.g << 8) | rgb.b;
  351. }
  352. }
  353. using Gfx::Color;
  354. namespace AK {
  355. template<>
  356. struct Formatter<Gfx::Color> : public Formatter<StringView> {
  357. void format(FormatBuilder& builder, const Gfx::Color& value);
  358. };
  359. }
  360. namespace IPC {
  361. bool encode(Encoder&, const Gfx::Color&);
  362. bool decode(Decoder&, Gfx::Color&);
  363. }