diff --git a/libs/gfx/include/psemek/gfx/color.hpp b/libs/gfx/include/psemek/gfx/color.hpp index 2233c1df..497267bb 100644 --- a/libs/gfx/include/psemek/gfx/color.hpp +++ b/libs/gfx/include/psemek/gfx/color.hpp @@ -5,6 +5,8 @@ #include #include +#include +#include namespace psemek::gfx { @@ -205,4 +207,6 @@ namespace psemek::gfx return generic_color{dark(c.c, darkness)}; } + std::optional parse_color(std::string_view const & text); + } diff --git a/libs/gfx/source/color.cpp b/libs/gfx/source/color.cpp new file mode 100644 index 00000000..2fb44d38 --- /dev/null +++ b/libs/gfx/source/color.cpp @@ -0,0 +1,110 @@ +#include + +#include + +namespace psemek::gfx +{ + + static std::unordered_map const named_colors + { + {"black", {0, 0, 0, 255}}, + {"white", {255, 255, 255, 255}}, + {"grey", {127, 127, 127, 255}}, + + {"red", {255, 0, 0, 255}}, + {"green", {0, 255, 0, 255}}, + {"blue", {0, 0, 255, 255}}, + {"cyan", {0, 255, 255, 255}}, + {"magenta", {255, 0, 255, 255}}, + {"yellow", {255, 255, 0, 255}}, + + {"dark_grey", {63, 63, 63, 255}}, + {"light_grey", {191, 191, 191, 255}}, + + {"dark_red", {127, 0, 0, 255}}, + {"dark_green", {0, 127, 0, 255}}, + {"dark_blue", {0, 0, 127, 255}}, + {"dark_cyan", {0, 127, 127, 255}}, + {"dark_magenta", {127, 0, 127, 255}}, + {"dark_yellow", {127, 127, 0, 255}}, + + {"light_red", {255, 127, 127, 255}}, + {"light_green", {127, 255, 127, 255}}, + {"light_blue", {127, 127, 255, 255}}, + {"light_cyan", {127, 255, 255, 255}}, + {"light_magenta", {255, 127, 255, 255}}, + {"light_yellow", {255, 255, 127, 255}}, + }; + + static bool all_hex(std::string_view const & text) + { + return std::all_of(text.begin(), text.end(), [](char c){ + return ('0' <= c && c <= '9') || ('a' <= c && c <= 'f') || ('A' <= c && c <= 'F'); + }); + } + + static std::uint8_t from_hex(char c) + { + if ('0' <= c && c <= '9') + return c - '0'; + if ('a' <= c && c <= 'f') + return 10 + (c - 'a'); + if ('A' <= c && c <= 'F') + return 10 + (c - 'A'); + return 0; + } + + static std::uint8_t from_hex(char c1, char c0) + { + return (from_hex(c1) * 16) | from_hex(c0); + } + + std::optional parse_color(std::string_view const & text) + { + if (auto it = named_colors.find(text); it != named_colors.end()) + return it->second; + + if (all_hex(text)) + { + if (text.size() == 3) + { + return color_rgba{ + 17 * from_hex(text[0]), + 17 * from_hex(text[1]), + 17 * from_hex(text[2]), + 255 + }; + } + else if (text.size() == 4) + { + return color_rgba{ + 17 * from_hex(text[0]), + 17 * from_hex(text[1]), + 17 * from_hex(text[2]), + 17 * from_hex(text[3]), + }; + } + else if (text.size() == 6) + { + return color_rgba{ + from_hex(text[0], text[1]), + from_hex(text[2], text[3]), + from_hex(text[4], text[5]), + 255 + }; + } + else if (text.size() == 8) + { + return color_rgba{ + from_hex(text[0], text[1]), + from_hex(text[2], text[3]), + from_hex(text[4], text[5]), + from_hex(text[6], text[7]), + }; + } + } + + return std::nullopt; + } + +}