psemek/libs/gfx/source/color.cpp

109 lines
2.4 KiB
C++

#include <psemek/gfx/color.hpp>
#include <psemek/util/hash_table.hpp>
namespace psemek::gfx
{
static util::hash_map<std::string_view, color_rgba> 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<color_rgba> 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;
}
}