20 static unsigned short roundColor(
unsigned short c) {
21 return c <= 255 ? c : 255;
24 static float roundColorF(
float f) {
return std::clamp(f, 0.0F, 1.0F); }
26 static unsigned short extendColor(
unsigned short c) {
31 static inline char to_hex_char(
int v) {
32 return (
char)(((v) >= 0 && (v) < 10) ? (v +
'0') : (v - 10 +
'a'));
35 static inline unsigned short to_hex_digit(
char hi,
char lo) {
36 hi = charutils::tolower(hi);
37 lo = charutils::tolower(lo);
40 if (hi >=
'0' && hi <=
'9') {
45 if (lo >=
'0' && lo <=
'9') {
51 return (dhi * 16) + dlo;
54 Color::Color(
unsigned short r,
unsigned short g,
unsigned short b,
56 : red_(extendColor(r)), green_(extendColor(g)), blue_(extendColor(b)),
57 alpha_(extendColor(alpha)) {}
59 Color::Color() : red_(0), green_(0), blue_(0), alpha_(USHRT_MAX) {}
61 bool Color::operator==(
const Color &other)
const {
62 return red_ == other.red_ && green_ == other.green_ &&
63 blue_ == other.blue_ && alpha_ == other.alpha_;
66 void Color::setFromString(
const char *str) {
70 while (str[idx] && charutils::isspace(str[idx])) {
74 if (str[idx] ==
'#') {
77 const char *digits = &str[idx + 1];
79 (charutils::isdigit(digits[len]) ||
80 (
'A' <= digits[len] && digits[len] <=
'F') |
81 (
'a' <= digits[len] && digits[len] <=
'f'))) {
84 if (len != 8 && len != 6) {
85 throw ColorParseException();
92 r = to_hex_digit(digits[0], digits[1]);
94 g = to_hex_digit(digits[0], digits[1]);
96 b = to_hex_digit(digits[0], digits[1]);
99 a = to_hex_digit(digits[0], digits[1]);
104 red_ = extendColor(r);
105 green_ = extendColor(g);
106 blue_ = extendColor(b);
107 alpha_ = extendColor(a);
112 if (sscanf(str,
"%hu %hu %hu", &r, &g, &b) != 3) {
113 throw ColorParseException();
116 red_ = extendColor(r);
117 green_ = extendColor(g);
118 blue_ = extendColor(b);
119 alpha_ = extendColor(255);
125 result.push_back(
'#');
126 unsigned short v[] = {
127 static_cast<unsigned short>(red_ >> 8U),
128 static_cast<unsigned short>(green_ >> 8U),
129 static_cast<unsigned short>(blue_ >> 8U),
130 static_cast<unsigned short>(alpha_ >> 8U),
133 for (
auto value : v) {
134 auto hi = value / 16;
135 auto lo = value % 16;
136 result.push_back(to_hex_char(hi));
137 result.push_back(to_hex_char(lo));
140 result.erase(result.size() - 2, 2);
146 unsigned short Color::red()
const {
return red_ >> 8; }
147 unsigned short Color::green()
const {
return green_ >> 8; }
148 unsigned short Color::blue()
const {
return blue_ >> 8; }
149 unsigned short Color::alpha()
const {
return alpha_ >> 8; }
151 float Color::redF()
const {
return red_ / float(USHRT_MAX); }
152 float Color::greenF()
const {
return green_ / float(USHRT_MAX); }
153 float Color::blueF()
const {
return blue_ / float(USHRT_MAX); }
154 float Color::alphaF()
const {
return alpha_ / float(USHRT_MAX); }
156 void Color::setRed(
unsigned short red) { red_ = extendColor(red); }
157 void Color::setGreen(
unsigned short green) { green_ = extendColor(green); }
158 void Color::setBlue(
unsigned short blue) { blue_ = extendColor(blue); }
159 void Color::setAlpha(
unsigned short alpha) { alpha_ = extendColor(alpha); }
161 void Color::setRedF(
float red) {
162 red_ = std::round(roundColorF(red) * USHRT_MAX);
164 void Color::setGreenF(
float green) {
165 green_ = std::round(roundColorF(green) * USHRT_MAX);
167 void Color::setBlueF(
float blue) {
168 blue_ = std::round(roundColorF(blue) * USHRT_MAX);
170 void Color::setAlphaF(
float alpha) {
171 alpha_ = std::round(roundColorF(alpha) * USHRT_MAX);
174 std::ostream &operator<<(std::ostream &os,
const Color &c) {
175 os <<
"Color(" << c.
toString() <<
")";
std::string toString() const
Get color string in the format of "#rrggbbaa".
bool endsWith(std::string_view str, std::string_view suffix)
Check if a string ends with a suffix.
Color class for handling color.
Simple color class that represent a 64bit color.
Local independent API to detect character type.