Color.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411
  1. /*
  2. * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
  3. * Copyright (c) 2019-2023, Shannon Booth <shannon@serenityos.org>
  4. *
  5. * SPDX-License-Identifier: BSD-2-Clause
  6. */
  7. #include <AK/Assertions.h>
  8. #include <AK/ByteString.h>
  9. #include <AK/FloatingPointStringConversions.h>
  10. #include <AK/Optional.h>
  11. #include <AK/Swift.h>
  12. #include <AK/Vector.h>
  13. #include <LibGfx/Color.h>
  14. #include <LibGfx/SystemTheme.h>
  15. #include <LibIPC/Decoder.h>
  16. #include <LibIPC/Encoder.h>
  17. #include <ctype.h>
  18. #ifdef LIBGFX_USE_SWIFT
  19. # include <LibGfx-Swift.h>
  20. #endif
  21. namespace Gfx {
  22. String Color::to_string() const
  23. {
  24. return MUST(String::formatted("#{:02x}{:02x}{:02x}{:02x}", red(), green(), blue(), alpha()));
  25. }
  26. String Color::to_string_without_alpha() const
  27. {
  28. return MUST(String::formatted("#{:02x}{:02x}{:02x}", red(), green(), blue()));
  29. }
  30. ByteString Color::to_byte_string() const
  31. {
  32. return to_string().to_byte_string();
  33. }
  34. ByteString Color::to_byte_string_without_alpha() const
  35. {
  36. return to_string_without_alpha().to_byte_string();
  37. }
  38. static Optional<Color> parse_rgb_color(StringView string)
  39. {
  40. VERIFY(string.starts_with("rgb("sv, CaseSensitivity::CaseInsensitive));
  41. VERIFY(string.ends_with(')'));
  42. auto substring = string.substring_view(4, string.length() - 5);
  43. auto parts = substring.split_view(',');
  44. if (parts.size() != 3)
  45. return {};
  46. auto r = parts[0].to_number<double>().map(AK::clamp_to<u8, double>);
  47. auto g = parts[1].to_number<double>().map(AK::clamp_to<u8, double>);
  48. auto b = parts[2].to_number<double>().map(AK::clamp_to<u8, double>);
  49. if (!r.has_value() || !g.has_value() || !b.has_value())
  50. return {};
  51. return Color(*r, *g, *b);
  52. }
  53. static Optional<Color> parse_rgba_color(StringView string)
  54. {
  55. VERIFY(string.starts_with("rgba("sv, CaseSensitivity::CaseInsensitive));
  56. VERIFY(string.ends_with(')'));
  57. auto substring = string.substring_view(5, string.length() - 6);
  58. auto parts = substring.split_view(',');
  59. if (parts.size() != 4)
  60. return {};
  61. auto r = parts[0].to_number<double>().map(AK::clamp_to<u8, double>);
  62. auto g = parts[1].to_number<double>().map(AK::clamp_to<u8, double>);
  63. auto b = parts[2].to_number<double>().map(AK::clamp_to<u8, double>);
  64. double alpha = 0;
  65. auto alpha_str = parts[3].trim_whitespace();
  66. char const* start = alpha_str.characters_without_null_termination();
  67. auto alpha_result = parse_first_floating_point(start, start + alpha_str.length());
  68. if (alpha_result.parsed_value())
  69. alpha = alpha_result.value;
  70. unsigned a = alpha * 255;
  71. if (!r.has_value() || !g.has_value() || !b.has_value() || a > 255)
  72. return {};
  73. return Color(*r, *g, *b, a);
  74. }
  75. Optional<Color> Color::from_named_css_color_string(StringView string)
  76. {
  77. if (string.is_empty())
  78. return {};
  79. struct WebColor {
  80. ARGB32 color;
  81. StringView name;
  82. };
  83. constexpr Array web_colors {
  84. // CSS Level 1
  85. WebColor { 0x000000, "black"sv },
  86. WebColor { 0xc0c0c0, "silver"sv },
  87. WebColor { 0x808080, "gray"sv },
  88. WebColor { 0xffffff, "white"sv },
  89. WebColor { 0x800000, "maroon"sv },
  90. WebColor { 0xff0000, "red"sv },
  91. WebColor { 0x800080, "purple"sv },
  92. WebColor { 0xff00ff, "fuchsia"sv },
  93. WebColor { 0x008000, "green"sv },
  94. WebColor { 0x00ff00, "lime"sv },
  95. WebColor { 0x808000, "olive"sv },
  96. WebColor { 0xffff00, "yellow"sv },
  97. WebColor { 0x000080, "navy"sv },
  98. WebColor { 0x0000ff, "blue"sv },
  99. WebColor { 0x008080, "teal"sv },
  100. WebColor { 0x00ffff, "aqua"sv },
  101. // CSS Level 2 (Revision 1)
  102. WebColor { 0xffa500, "orange"sv },
  103. // CSS Color Module Level 3
  104. WebColor { 0xf0f8ff, "aliceblue"sv },
  105. WebColor { 0xfaebd7, "antiquewhite"sv },
  106. WebColor { 0x7fffd4, "aquamarine"sv },
  107. WebColor { 0xf0ffff, "azure"sv },
  108. WebColor { 0xf5f5dc, "beige"sv },
  109. WebColor { 0xffe4c4, "bisque"sv },
  110. WebColor { 0xffebcd, "blanchedalmond"sv },
  111. WebColor { 0x8a2be2, "blueviolet"sv },
  112. WebColor { 0xa52a2a, "brown"sv },
  113. WebColor { 0xdeb887, "burlywood"sv },
  114. WebColor { 0x5f9ea0, "cadetblue"sv },
  115. WebColor { 0x7fff00, "chartreuse"sv },
  116. WebColor { 0xd2691e, "chocolate"sv },
  117. WebColor { 0xff7f50, "coral"sv },
  118. WebColor { 0x6495ed, "cornflowerblue"sv },
  119. WebColor { 0xfff8dc, "cornsilk"sv },
  120. WebColor { 0xdc143c, "crimson"sv },
  121. WebColor { 0x00ffff, "cyan"sv },
  122. WebColor { 0x00008b, "darkblue"sv },
  123. WebColor { 0x008b8b, "darkcyan"sv },
  124. WebColor { 0xb8860b, "darkgoldenrod"sv },
  125. WebColor { 0xa9a9a9, "darkgray"sv },
  126. WebColor { 0x006400, "darkgreen"sv },
  127. WebColor { 0xa9a9a9, "darkgrey"sv },
  128. WebColor { 0xbdb76b, "darkkhaki"sv },
  129. WebColor { 0x8b008b, "darkmagenta"sv },
  130. WebColor { 0x556b2f, "darkolivegreen"sv },
  131. WebColor { 0xff8c00, "darkorange"sv },
  132. WebColor { 0x9932cc, "darkorchid"sv },
  133. WebColor { 0x8b0000, "darkred"sv },
  134. WebColor { 0xe9967a, "darksalmon"sv },
  135. WebColor { 0x8fbc8f, "darkseagreen"sv },
  136. WebColor { 0x483d8b, "darkslateblue"sv },
  137. WebColor { 0x2f4f4f, "darkslategray"sv },
  138. WebColor { 0x2f4f4f, "darkslategrey"sv },
  139. WebColor { 0x00ced1, "darkturquoise"sv },
  140. WebColor { 0x9400d3, "darkviolet"sv },
  141. WebColor { 0xff1493, "deeppink"sv },
  142. WebColor { 0x00bfff, "deepskyblue"sv },
  143. WebColor { 0x696969, "dimgray"sv },
  144. WebColor { 0x696969, "dimgrey"sv },
  145. WebColor { 0x1e90ff, "dodgerblue"sv },
  146. WebColor { 0xb22222, "firebrick"sv },
  147. WebColor { 0xfffaf0, "floralwhite"sv },
  148. WebColor { 0x228b22, "forestgreen"sv },
  149. WebColor { 0xdcdcdc, "gainsboro"sv },
  150. WebColor { 0xf8f8ff, "ghostwhite"sv },
  151. WebColor { 0xffd700, "gold"sv },
  152. WebColor { 0xdaa520, "goldenrod"sv },
  153. WebColor { 0xadff2f, "greenyellow"sv },
  154. WebColor { 0x808080, "grey"sv },
  155. WebColor { 0xf0fff0, "honeydew"sv },
  156. WebColor { 0xff69b4, "hotpink"sv },
  157. WebColor { 0xcd5c5c, "indianred"sv },
  158. WebColor { 0x4b0082, "indigo"sv },
  159. WebColor { 0xfffff0, "ivory"sv },
  160. WebColor { 0xf0e68c, "khaki"sv },
  161. WebColor { 0xe6e6fa, "lavender"sv },
  162. WebColor { 0xfff0f5, "lavenderblush"sv },
  163. WebColor { 0x7cfc00, "lawngreen"sv },
  164. WebColor { 0xfffacd, "lemonchiffon"sv },
  165. WebColor { 0xadd8e6, "lightblue"sv },
  166. WebColor { 0xf08080, "lightcoral"sv },
  167. WebColor { 0xe0ffff, "lightcyan"sv },
  168. WebColor { 0xfafad2, "lightgoldenrodyellow"sv },
  169. WebColor { 0xd3d3d3, "lightgray"sv },
  170. WebColor { 0x90ee90, "lightgreen"sv },
  171. WebColor { 0xd3d3d3, "lightgrey"sv },
  172. WebColor { 0xffb6c1, "lightpink"sv },
  173. WebColor { 0xffa07a, "lightsalmon"sv },
  174. WebColor { 0x20b2aa, "lightseagreen"sv },
  175. WebColor { 0x87cefa, "lightskyblue"sv },
  176. WebColor { 0x778899, "lightslategray"sv },
  177. WebColor { 0x778899, "lightslategrey"sv },
  178. WebColor { 0xb0c4de, "lightsteelblue"sv },
  179. WebColor { 0xffffe0, "lightyellow"sv },
  180. WebColor { 0x32cd32, "limegreen"sv },
  181. WebColor { 0xfaf0e6, "linen"sv },
  182. WebColor { 0xff00ff, "magenta"sv },
  183. WebColor { 0x66cdaa, "mediumaquamarine"sv },
  184. WebColor { 0x0000cd, "mediumblue"sv },
  185. WebColor { 0xba55d3, "mediumorchid"sv },
  186. WebColor { 0x9370db, "mediumpurple"sv },
  187. WebColor { 0x3cb371, "mediumseagreen"sv },
  188. WebColor { 0x7b68ee, "mediumslateblue"sv },
  189. WebColor { 0x00fa9a, "mediumspringgreen"sv },
  190. WebColor { 0x48d1cc, "mediumturquoise"sv },
  191. WebColor { 0xc71585, "mediumvioletred"sv },
  192. WebColor { 0x191970, "midnightblue"sv },
  193. WebColor { 0xf5fffa, "mintcream"sv },
  194. WebColor { 0xffe4e1, "mistyrose"sv },
  195. WebColor { 0xffe4b5, "moccasin"sv },
  196. WebColor { 0xffdead, "navajowhite"sv },
  197. WebColor { 0xfdf5e6, "oldlace"sv },
  198. WebColor { 0x6b8e23, "olivedrab"sv },
  199. WebColor { 0xff4500, "orangered"sv },
  200. WebColor { 0xda70d6, "orchid"sv },
  201. WebColor { 0xeee8aa, "palegoldenrod"sv },
  202. WebColor { 0x98fb98, "palegreen"sv },
  203. WebColor { 0xafeeee, "paleturquoise"sv },
  204. WebColor { 0xdb7093, "palevioletred"sv },
  205. WebColor { 0xffefd5, "papayawhip"sv },
  206. WebColor { 0xffdab9, "peachpuff"sv },
  207. WebColor { 0xcd853f, "peru"sv },
  208. WebColor { 0xffc0cb, "pink"sv },
  209. WebColor { 0xdda0dd, "plum"sv },
  210. WebColor { 0xb0e0e6, "powderblue"sv },
  211. WebColor { 0xbc8f8f, "rosybrown"sv },
  212. WebColor { 0x4169e1, "royalblue"sv },
  213. WebColor { 0x8b4513, "saddlebrown"sv },
  214. WebColor { 0xfa8072, "salmon"sv },
  215. WebColor { 0xf4a460, "sandybrown"sv },
  216. WebColor { 0x2e8b57, "seagreen"sv },
  217. WebColor { 0xfff5ee, "seashell"sv },
  218. WebColor { 0xa0522d, "sienna"sv },
  219. WebColor { 0x87ceeb, "skyblue"sv },
  220. WebColor { 0x6a5acd, "slateblue"sv },
  221. WebColor { 0x708090, "slategray"sv },
  222. WebColor { 0x708090, "slategrey"sv },
  223. WebColor { 0xfffafa, "snow"sv },
  224. WebColor { 0x00ff7f, "springgreen"sv },
  225. WebColor { 0x4682b4, "steelblue"sv },
  226. WebColor { 0xd2b48c, "tan"sv },
  227. WebColor { 0xd8bfd8, "thistle"sv },
  228. WebColor { 0xff6347, "tomato"sv },
  229. WebColor { 0x40e0d0, "turquoise"sv },
  230. WebColor { 0xee82ee, "violet"sv },
  231. WebColor { 0xf5deb3, "wheat"sv },
  232. WebColor { 0xf5f5f5, "whitesmoke"sv },
  233. WebColor { 0x9acd32, "yellowgreen"sv },
  234. // CSS Color Module Level 4
  235. WebColor { 0x663399, "rebeccapurple"sv },
  236. };
  237. for (auto const& web_color : web_colors) {
  238. if (string.equals_ignoring_ascii_case(web_color.name))
  239. return Color::from_rgb(web_color.color);
  240. }
  241. return {};
  242. }
  243. #if defined(LIBGFX_USE_SWIFT)
  244. static Optional<Color> hex_string_to_color(StringView string)
  245. {
  246. auto color = SwiftLibGfx::parseHexString(string);
  247. if (color.getCount() == 0)
  248. return {};
  249. return color[0];
  250. }
  251. #else
  252. static Optional<Color> hex_string_to_color(StringView string)
  253. {
  254. auto hex_nibble_to_u8 = [](char nibble) -> Optional<u8> {
  255. if (!isxdigit(nibble))
  256. return {};
  257. if (nibble >= '0' && nibble <= '9')
  258. return nibble - '0';
  259. return 10 + (tolower(nibble) - 'a');
  260. };
  261. if (string.length() == 4) {
  262. Optional<u8> r = hex_nibble_to_u8(string[1]);
  263. Optional<u8> g = hex_nibble_to_u8(string[2]);
  264. Optional<u8> b = hex_nibble_to_u8(string[3]);
  265. if (!r.has_value() || !g.has_value() || !b.has_value())
  266. return {};
  267. return Color(r.value() * 17, g.value() * 17, b.value() * 17);
  268. }
  269. if (string.length() == 5) {
  270. Optional<u8> r = hex_nibble_to_u8(string[1]);
  271. Optional<u8> g = hex_nibble_to_u8(string[2]);
  272. Optional<u8> b = hex_nibble_to_u8(string[3]);
  273. Optional<u8> a = hex_nibble_to_u8(string[4]);
  274. if (!r.has_value() || !g.has_value() || !b.has_value() || !a.has_value())
  275. return {};
  276. return Color(r.value() * 17, g.value() * 17, b.value() * 17, a.value() * 17);
  277. }
  278. if (string.length() != 7 && string.length() != 9)
  279. return {};
  280. auto to_hex = [&](char c1, char c2) -> Optional<u8> {
  281. auto nib1 = hex_nibble_to_u8(c1);
  282. auto nib2 = hex_nibble_to_u8(c2);
  283. if (!nib1.has_value() || !nib2.has_value())
  284. return {};
  285. return nib1.value() << 4 | nib2.value();
  286. };
  287. Optional<u8> r = to_hex(string[1], string[2]);
  288. Optional<u8> g = to_hex(string[3], string[4]);
  289. Optional<u8> b = to_hex(string[5], string[6]);
  290. Optional<u8> a = string.length() == 9 ? to_hex(string[7], string[8]) : Optional<u8>(255);
  291. if (!r.has_value() || !g.has_value() || !b.has_value() || !a.has_value())
  292. return {};
  293. return Color(r.value(), g.value(), b.value(), a.value());
  294. }
  295. #endif
  296. Optional<Color> Color::from_string(StringView string)
  297. {
  298. if (string.is_empty())
  299. return {};
  300. if (string[0] == '#')
  301. return hex_string_to_color(string);
  302. if (string.starts_with("rgb("sv, CaseSensitivity::CaseInsensitive) && string.ends_with(')'))
  303. return parse_rgb_color(string);
  304. if (string.starts_with("rgba("sv, CaseSensitivity::CaseInsensitive) && string.ends_with(')'))
  305. return parse_rgba_color(string);
  306. if (string.equals_ignoring_ascii_case("transparent"sv))
  307. return Color::from_argb(0x00000000);
  308. if (auto const color = from_named_css_color_string(string); color.has_value())
  309. return color;
  310. return {};
  311. }
  312. Vector<Color> Color::shades(u32 steps, float max) const
  313. {
  314. float shade = 1.f;
  315. float step = max / steps;
  316. Vector<Color> shades;
  317. for (u32 i = 0; i < steps; i++) {
  318. shade -= step;
  319. shades.append(this->darkened(shade));
  320. }
  321. return shades;
  322. }
  323. Vector<Color> Color::tints(u32 steps, float max) const
  324. {
  325. float shade = 1.f;
  326. float step = max / steps;
  327. Vector<Color> tints;
  328. for (u32 i = 0; i < steps; i++) {
  329. shade += step;
  330. tints.append(this->lightened(shade));
  331. }
  332. return tints;
  333. }
  334. }
  335. template<>
  336. ErrorOr<void> IPC::encode(Encoder& encoder, Color const& color)
  337. {
  338. return encoder.encode(color.value());
  339. }
  340. template<>
  341. ErrorOr<Gfx::Color> IPC::decode(Decoder& decoder)
  342. {
  343. auto rgba = TRY(decoder.decode<u32>());
  344. return Gfx::Color::from_argb(rgba);
  345. }
  346. ErrorOr<void> AK::Formatter<Gfx::Color>::format(FormatBuilder& builder, Gfx::Color value)
  347. {
  348. return Formatter<StringView>::format(builder, value.to_byte_string());
  349. }
  350. ErrorOr<void> AK::Formatter<Gfx::YUV>::format(FormatBuilder& builder, Gfx::YUV value)
  351. {
  352. return Formatter<FormatString>::format(builder, "{} {} {}"sv, value.y, value.u, value.v);
  353. }
  354. ErrorOr<void> AK::Formatter<Gfx::HSV>::format(FormatBuilder& builder, Gfx::HSV value)
  355. {
  356. return Formatter<FormatString>::format(builder, "{} {} {}"sv, value.hue, value.saturation, value.value);
  357. }
  358. ErrorOr<void> AK::Formatter<Gfx::Oklab>::format(FormatBuilder& builder, Gfx::Oklab value)
  359. {
  360. return Formatter<FormatString>::format(builder, "{} {} {}"sv, value.L, value.a, value.b);
  361. }