109 lines
2.4 KiB
C++
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;
|
|
}
|
|
|
|
}
|