Allow specifying lighter or darker variants of built-in colors.
This commit is contained in:
parent
1854ef34e6
commit
722086781d
116
Color.cpp
116
Color.cpp
@ -4,6 +4,9 @@
|
|||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <cstring>
|
||||||
|
#include <sstream>
|
||||||
|
#include <iomanip>
|
||||||
#include <cctype>
|
#include <cctype>
|
||||||
#include "Color.h"
|
#include "Color.h"
|
||||||
|
|
||||||
@ -47,32 +50,38 @@ ColorTable colorTable;
|
|||||||
// -1: allow alpha but ignore - set to to 255 (0xff)
|
// -1: allow alpha but ignore - set to to 255 (0xff)
|
||||||
Color::Color(std::string color, int alpha)
|
Color::Color(std::string color, int alpha)
|
||||||
{
|
{
|
||||||
if (color[0] != '#') {
|
size_t pos = color.find_first_of("+-");
|
||||||
int l = color.length();
|
std::string basecolor = color.substr(0, pos);
|
||||||
|
std::string colormod;
|
||||||
|
if (pos != std::string::npos)
|
||||||
|
colormod = color.substr(pos);
|
||||||
|
do {
|
||||||
|
if (basecolor[0] != '#') {
|
||||||
|
int l = basecolor.length();
|
||||||
for (int i = 0; i < l; i++)
|
for (int i = 0; i < l; i++)
|
||||||
color[i] = tolower(color[i]);
|
basecolor[i] = tolower(basecolor[i]);
|
||||||
if (colorTable.count(color) > 0) {
|
if (colorTable.count(basecolor) > 0) {
|
||||||
*this = colorTable[color];
|
*this = colorTable[basecolor];
|
||||||
return;
|
break;
|
||||||
}
|
}
|
||||||
throw std::runtime_error(std::string("Symbolic color '") + color + "' not known, or color does not begin with #");
|
throw std::runtime_error(std::string("Symbolic color '") + color + "' not known, or color does not begin with #");
|
||||||
}
|
}
|
||||||
if (std::string::npos != color.find_first_not_of("0123456789abcdefABCDEF",1)) {
|
if (std::string::npos != basecolor.find_first_not_of("0123456789abcdefABCDEF",1)) {
|
||||||
throw std::runtime_error("Color value has invalid digits (expected: [0-9a-zA-Z])");
|
throw std::runtime_error("Color value has invalid digits (expected: [0-9a-zA-Z])");
|
||||||
}
|
}
|
||||||
if (alpha) {
|
if (alpha) {
|
||||||
if (color.length() != 4 && color.length() != 5 && color.length() != 7 && color.length() != 9)
|
if (basecolor.length() != 4 && basecolor.length() != 5 && basecolor.length() != 7 && basecolor.length() != 9)
|
||||||
throw std::runtime_error("Color not in the expected format (#xxx, #xxxx, #xxxxxx or #xxxxxxxx)");
|
throw std::runtime_error(std::string("Color '") + color + "' not in the expected format (#xxx, #xxxx, #xxxxxx or #xxxxxxxx)");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (color.length() == 5 || color.length() == 9)
|
if (basecolor.length() == 5 || basecolor.length() == 9)
|
||||||
throw std::runtime_error("Color not in the expected format (#xxx or #xxxxxx) - alpha not allowed");
|
throw std::runtime_error(std::string("Color '") + color + "' not in the expected format (#xxx or #xxxxxx) - alpha not allowed");
|
||||||
if (color.length() != 4 && color.length() != 7)
|
if (basecolor.length() != 4 && basecolor.length() != 7)
|
||||||
throw std::runtime_error("Color not in the expected format (#xxx or #xxxxxx)");
|
throw std::runtime_error(std::string("Color '") + color + "' not in the expected format (#xxx or #xxxxxx)");
|
||||||
}
|
}
|
||||||
unsigned col = strtoul(color.c_str() + 1, NULL, 16);
|
unsigned col = strtoul(basecolor.c_str() + 1, NULL, 16);
|
||||||
if (color.length() < 6) {
|
if (basecolor.length() < 6) {
|
||||||
if (color.length() == 5)
|
if (basecolor.length() == 5)
|
||||||
a = (col >> 12) & 0x0f;
|
a = (col >> 12) & 0x0f;
|
||||||
else
|
else
|
||||||
a = 0x0f;
|
a = 0x0f;
|
||||||
@ -85,7 +94,7 @@ Color::Color(std::string color, int alpha)
|
|||||||
b |= b << 4;
|
b |= b << 4;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (color.length() == 9)
|
if (basecolor.length() == 9)
|
||||||
a = (col >> 24) & 0xff;
|
a = (col >> 24) & 0xff;
|
||||||
else
|
else
|
||||||
a = 0xff;
|
a = 0xff;
|
||||||
@ -95,5 +104,78 @@ Color::Color(std::string color, int alpha)
|
|||||||
}
|
}
|
||||||
if (alpha <= 0)
|
if (alpha <= 0)
|
||||||
a = 0xff;
|
a = 0xff;
|
||||||
|
} while(false);
|
||||||
|
if (colormod.length() == 0)
|
||||||
|
return;
|
||||||
|
std::istringstream iss(colormod);
|
||||||
|
iss >> std::ws;
|
||||||
|
while (!iss.eof()) {
|
||||||
|
double w;
|
||||||
|
char operation;
|
||||||
|
char ccode='w';
|
||||||
|
iss >> operation;
|
||||||
|
iss >> ccode;
|
||||||
|
iss >> w >> std::ws;
|
||||||
|
if (w > 1)
|
||||||
|
w = w / 255;
|
||||||
|
if (!strchr("+-",operation) || !strchr("wkrgbcmy", ccode) || w < 0 || w > 1 || iss.fail())
|
||||||
|
throw std::runtime_error(std::string("Invalid color modification(s) (") + color + "); expected one or more of [+-][wkrgbcmy]<n> (n = 0..1)");
|
||||||
|
double v;
|
||||||
|
if (operation == '+' || operation == '-') {
|
||||||
|
// Mix in a color
|
||||||
|
int mixr = r;
|
||||||
|
int mixg = g;
|
||||||
|
int mixb = b;
|
||||||
|
if (operation == '+') {
|
||||||
|
if (ccode == 'w')
|
||||||
|
mixr = mixg = mixb = 255;
|
||||||
|
else if (operation == 'k')
|
||||||
|
mixr = mixg = mixb = 0;
|
||||||
|
else if (ccode == 'r')
|
||||||
|
mixr = 255;
|
||||||
|
else if (ccode == 'g')
|
||||||
|
mixg = 255;
|
||||||
|
else if (ccode == 'b')
|
||||||
|
mixb = 255;
|
||||||
|
else if (ccode == 'c')
|
||||||
|
mixg = mixb = 255;
|
||||||
|
else if (ccode == 'm')
|
||||||
|
mixr = mixb = 255;
|
||||||
|
else if (ccode == 'y')
|
||||||
|
mixr = mixg = 255;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (ccode == 'w')
|
||||||
|
mixr = mixg = mixb = 0;
|
||||||
|
else if (operation == 'k')
|
||||||
|
mixr = mixg = mixb = 255;
|
||||||
|
else if (ccode == 'r')
|
||||||
|
mixr = 0;
|
||||||
|
else if (ccode == 'g')
|
||||||
|
mixg = 0;
|
||||||
|
else if (ccode == 'b')
|
||||||
|
mixb = 0;
|
||||||
|
else if (ccode == 'c')
|
||||||
|
mixg = mixb = 0;
|
||||||
|
else if (ccode == 'm')
|
||||||
|
mixr = mixb = 0;
|
||||||
|
else if (ccode == 'y')
|
||||||
|
mixr = mixg = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
v = r * (1 - w) + mixr * w;
|
||||||
|
if (v < 0) v = 0;
|
||||||
|
else if (v > 255) v = 255;
|
||||||
|
r = int(v + 0.5);
|
||||||
|
v = g * (1 - w) + mixg * w;
|
||||||
|
if (v < 0) v = 0;
|
||||||
|
else if (v > 255) v = 255;
|
||||||
|
g = int(v + 0.5);
|
||||||
|
v = b * (1 - w) + mixb * w;
|
||||||
|
if (v < 0) v = 0;
|
||||||
|
else if (v > 255) v = 255;
|
||||||
|
b = int(v + 0.5);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -113,6 +113,8 @@ void usage()
|
|||||||
"\t\tyellow, magenta, fuchsia, cyan, aqua,\n"
|
"\t\tyellow, magenta, fuchsia, cyan, aqua,\n"
|
||||||
"\t\torange, chartreuse, pink, violet, springgreen, azure\n"
|
"\t\torange, chartreuse, pink, violet, springgreen, azure\n"
|
||||||
"\t\tbrown (= 50% orange)\n"
|
"\t\tbrown (= 50% orange)\n"
|
||||||
|
"\tAs well as <color>[+-][wkrgbcmy]<n>, where n = 0.0..1.0 (or 1.00001 .. 255)\n"
|
||||||
|
"\t\t[+-][wkrgbcmy]<n> mixes in or out white, black, red, green, blue, cyan, magenta, yellow\n"
|
||||||
"Geometry formats:\n"
|
"Geometry formats:\n"
|
||||||
"\t<width>x<heigth>[+|-<xoffset>+|-<yoffset>] (dimensions and corner)\n"
|
"\t<width>x<heigth>[+|-<xoffset>+|-<yoffset>] (dimensions and corner)\n"
|
||||||
"\t<xoffset>,<yoffset>+<width>+<height> (corner and dimensions)\n"
|
"\t<xoffset>,<yoffset>+<width>+<height> (corner and dimensions)\n"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user