19 static unsigned short roundColor(
unsigned short c) {
20 return c <= 255 ? c : 255;
23 static float roundColorF(
float f) {
return std::clamp(f, 0.0F, 1.0F); }
25 static unsigned short extendColor(
unsigned short c) {
30 static inline char to_hex_char(
int v) {
31 return (
char)(((v) >= 0 && (v) < 10) ? (v +
'0') : (v - 10 +
'a'));
34 static inline unsigned short to_hex_digit(
char hi,
char lo) {
35 hi = charutils::tolower(hi);
36 lo = charutils::tolower(lo);
39 if (hi >=
'0' && hi <=
'9') {
44 if (lo >=
'0' && lo <=
'9') {
50 return (dhi * 16) + dlo;
53 Color::Color(
unsigned short r,
unsigned short g,
unsigned short b,
55 : red_(extendColor(r)), green_(extendColor(g)), blue_(extendColor(b)),
56 alpha_(extendColor(alpha)) {}
58 Color::Color() : red_(0), green_(0), blue_(0), alpha_(USHRT_MAX) {}
60 bool Color::operator==(
const Color &other)
const {
61 return red_ == other.red_ && green_ == other.green_ &&
62 blue_ == other.blue_ && alpha_ == other.alpha_;
65 void Color::setFromString(
const char *str) {
69 while (str[idx] && charutils::isspace(str[idx])) {
73 if (str[idx] ==
'#') {
76 const char *digits = &str[idx + 1];
78 (charutils::isdigit(digits[len]) ||
79 (
'A' <= digits[len] && digits[len] <=
'F') |
80 (
'a' <= digits[len] && digits[len] <=
'f'))) {
83 if (len != 8 && len != 6) {
84 throw ColorParseException();
91 r = to_hex_digit(digits[0], digits[1]);
93 g = to_hex_digit(digits[0], digits[1]);
95 b = to_hex_digit(digits[0], digits[1]);
98 a = to_hex_digit(digits[0], digits[1]);
103 red_ = extendColor(r);
104 green_ = extendColor(g);
105 blue_ = extendColor(b);
106 alpha_ = extendColor(a);
111 if (sscanf(str,
"%hu %hu %hu", &r, &g, &b) != 3) {
112 throw ColorParseException();
115 red_ = extendColor(r);
116 green_ = extendColor(g);
117 blue_ = extendColor(b);
118 alpha_ = extendColor(255);
124 result.push_back(
'#');
125 unsigned short v[] = {
126 static_cast<unsigned short>(red_ >> 8U),
127 static_cast<unsigned short>(green_ >> 8U),
128 static_cast<unsigned short>(blue_ >> 8U),
129 static_cast<unsigned short>(alpha_ >> 8U),
132 for (
auto value : v) {
133 auto hi = value / 16;
134 auto lo = value % 16;
135 result.push_back(to_hex_char(hi));
136 result.push_back(to_hex_char(lo));
138 if (result.ends_with(
"ff")) {
139 result.erase(result.size() - 2, 2);
145 unsigned short Color::red()
const {
return red_ >> 8; }
146 unsigned short Color::green()
const {
return green_ >> 8; }
147 unsigned short Color::blue()
const {
return blue_ >> 8; }
148 unsigned short Color::alpha()
const {
return alpha_ >> 8; }
150 float Color::redF()
const {
return red_ / float(USHRT_MAX); }
151 float Color::greenF()
const {
return green_ / float(USHRT_MAX); }
152 float Color::blueF()
const {
return blue_ / float(USHRT_MAX); }
153 float Color::alphaF()
const {
return alpha_ / float(USHRT_MAX); }
155 void Color::setRed(
unsigned short red) { red_ = extendColor(red); }
156 void Color::setGreen(
unsigned short green) { green_ = extendColor(green); }
157 void Color::setBlue(
unsigned short blue) { blue_ = extendColor(blue); }
158 void Color::setAlpha(
unsigned short alpha) { alpha_ = extendColor(alpha); }
160 void Color::setRedF(
float red) {
161 red_ = std::round(roundColorF(red) * USHRT_MAX);
163 void Color::setGreenF(
float green) {
164 green_ = std::round(roundColorF(green) * USHRT_MAX);
166 void Color::setBlueF(
float blue) {
167 blue_ = std::round(roundColorF(blue) * USHRT_MAX);
169 void Color::setAlphaF(
float alpha) {
170 alpha_ = std::round(roundColorF(alpha) * USHRT_MAX);
173 std::ostream &operator<<(std::ostream &os,
const Color &c) {
174 os <<
"Color(" << c.
toString() <<
")";
std::string toString() const
Get color string in the format of "#rrggbbaa".
Color class for handling color.
Simple color class that represent a 64bit color.
Local independent API to detect character type.