66 if (hex_color.substr(0, prefix.size()) != prefix) {
67 throw std::invalid_argument(
"String does not start with given prefix.");
69 auto const h =
utils::trim( hex_color.substr( prefix.size() ));
73 if( h.find_first_not_of(
"0123456789abcdefABCDEF") != std::string::npos ) {
74 throw std::invalid_argument(
"Expects string with six or eight hexadecimal digits.");
78 auto hex_parse = [&h] (
size_t pos) {
81 auto s = h.substr(pos * 2, 2);
82 auto v = std::stoul(s,
nullptr, 16);
87 return static_cast<double>(v) / 255.0;
92 return Color( hex_parse(0), hex_parse(1), hex_parse(2) );
93 }
else if( h.size() == 8 ) {
94 return Color( hex_parse(0), hex_parse(1), hex_parse(2), hex_parse(3) );
96 throw std::invalid_argument(
"Expects string with six or eight hexadecimal digits.");
101 Color const& c , std::string
const& prefix,
bool uppercase,
bool with_alpha
103 std::stringstream stream;
106 auto hex_print = [&stream, uppercase] (
unsigned char v) {
108 stream << std::setfill (
'0') << std::setw(2) << std::hex << std::uppercase
109 <<
static_cast<int>(v);
111 stream << std::setfill (
'0') << std::setw(2) << std::hex << std::nouppercase
112 <<
static_cast<int>(v);
140 auto const str =
trim( color_str );
157 auto interpolate_values = [](
double d1,
double d2,
double fraction )
159 return (1.0 - fraction) * d1 + fraction * d2;
162 fraction = std::min( std::max( 0.0, fraction ), 1.0 );
163 double r = interpolate_values( color1.
r(), color2.
r(), fraction );
164 double g = interpolate_values( color1.
g(), color2.
g(), fraction );
165 double b = interpolate_values( color1.
b(), color2.
b(), fraction );
166 double a = interpolate_values( color1.
a(), color2.
a(), fraction );
167 return Color( r, g, b, a );
173 if( ranges.size() < 2 ) {
174 throw std::invalid_argument(
"Gradient range needs to contain at least two colors.");
178 double const min = ranges.begin()->first;
179 double const max = ranges.rbegin()->first;
182 value = std::min( std::max( min, value ), max );
187 auto hi_bound = ranges.upper_bound( value );
188 auto lo_bound = std::prev( hi_bound );
189 assert( lo_bound != ranges.end() );
191 if( hi_bound == ranges.end() ) {
194 assert( value == max );
195 return ranges.rbegin()->second;
199 value = ( value - lo_bound->first ) / ( hi_bound->first - lo_bound->first );
200 return interpolate( lo_bound->second, hi_bound->second, value );
205 Color red { 1.0, 0.0, 0.0 };
206 Color yellow { 1.0, 1.0, 0.0 };
207 Color green { 0.0, 1.0, 0.0 };
209 percentage = std::min(std::max(0.0, percentage), 1.0);
211 if (percentage < 0.5) {
212 return interpolate(green, yellow, percentage / 0.5);
214 return interpolate(yellow, red, (percentage - 0.5) / 0.5);