Tidy up Color
parent
b0eb0675d7
commit
b5b3d29fa3
|
@ -1,45 +1,44 @@
|
|||
|
||||
#include <cctype>
|
||||
#include <stdexcept>
|
||||
#include <cstdlib>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <cstring>
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
#include <cctype>
|
||||
#include "Color.h"
|
||||
#include "util.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cctype>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <iomanip>
|
||||
#include <map>
|
||||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
|
||||
class ColorTable : public std::map<std::string, Color>
|
||||
{
|
||||
public:
|
||||
ColorTable(void)
|
||||
ColorTable()
|
||||
{
|
||||
map<std::string, Color> &table = *this;
|
||||
table["white"] = Color(0xff, 0xff, 0xff);
|
||||
table["black"] = Color(0, 0, 0);
|
||||
table["gray"] = Color(0x7f, 0x7f, 0x7f);
|
||||
table["grey"] = Color(0x7f, 0x7f, 0x7f);
|
||||
map<std::string, Color> &table = *this;
|
||||
table["white"] = Color(0xff, 0xff, 0xff);
|
||||
table["black"] = Color(0, 0, 0);
|
||||
table["gray"] = Color(0x7f, 0x7f, 0x7f);
|
||||
table["grey"] = Color(0x7f, 0x7f, 0x7f);
|
||||
|
||||
table["red"] = Color(0xff, 0, 0);
|
||||
table["green"] = Color(0, 0xff, 0);
|
||||
table["blue"] = Color(0, 0, 0xff);
|
||||
table["red"] = Color(0xff, 0, 0);
|
||||
table["green"] = Color(0, 0xff, 0);
|
||||
table["blue"] = Color(0, 0, 0xff);
|
||||
|
||||
table["yellow"] = Color(0xff, 0xff, 0);
|
||||
table["magenta"] = Color(0xff, 0, 0xff);
|
||||
table["fuchsia"] = Color(0xff, 0, 0xff);
|
||||
table["cyan"] = Color(0, 0xff, 0xff);
|
||||
table["aqua"] = Color(0, 0xff, 0xff);
|
||||
table["yellow"] = Color(0xff, 0xff, 0);
|
||||
table["magenta"] = Color(0xff, 0, 0xff);
|
||||
table["fuchsia"] = Color(0xff, 0, 0xff);
|
||||
table["cyan"] = Color(0, 0xff, 0xff);
|
||||
table["aqua"] = Color(0, 0xff, 0xff);
|
||||
|
||||
table["orange"] = Color(0xff, 0x7f, 0);
|
||||
table["chartreuse"] = Color(0x7f, 0xff, 0);
|
||||
table["pink"] = Color(0xff, 0, 0x7f);
|
||||
table["violet"] = Color(0x7f, 0, 0xff);
|
||||
table["springgreen"] = Color(0, 0xff, 0x7f);
|
||||
table["azure"] = Color(0, 0x7f, 0xff);
|
||||
table["orange"] = Color(0xff, 0x7f, 0);
|
||||
table["chartreuse"] = Color(0x7f, 0xff, 0);
|
||||
table["pink"] = Color(0xff, 0, 0x7f);
|
||||
table["violet"] = Color(0x7f, 0, 0xff);
|
||||
table["springgreen"] = Color(0, 0xff, 0x7f);
|
||||
table["azure"] = Color(0, 0x7f, 0xff);
|
||||
|
||||
table["brown"] = Color(0x7f, 0x3f, 0);
|
||||
table["brown"] = Color(0x7f, 0x3f, 0);
|
||||
}
|
||||
};
|
||||
ColorTable colorTable;
|
||||
|
@ -49,41 +48,50 @@ ColorTable colorTable;
|
|||
// 0: don't expect/allow alpha
|
||||
// 1: allow alpha; defaults to 255 (0xff)
|
||||
// -1: allow alpha but ignore - set to to 255 (0xff)
|
||||
Color::Color(std::string color, int alpha)
|
||||
Color::Color(const std::string &color, int alpha)
|
||||
{
|
||||
size_t pos = color.find_first_of("+-");
|
||||
std::string basecolor = color.substr(0, pos);
|
||||
std::string colormod;
|
||||
if (pos != std::string::npos)
|
||||
if (pos != std::string::npos) {
|
||||
colormod = color.substr(pos);
|
||||
do {
|
||||
if (basecolor[0] != '#') {
|
||||
basecolor = strlower(basecolor);
|
||||
if (colorTable.count(basecolor) > 0) {
|
||||
*this = colorTable[basecolor];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (basecolor[0] != '#') { // Color name
|
||||
std::transform(basecolor.begin(), basecolor.end(), basecolor.begin(), ::tolower);
|
||||
if (colorTable.count(basecolor) > 0) {
|
||||
*this = colorTable[basecolor];
|
||||
}
|
||||
else {
|
||||
throw std::runtime_error(std::string("Symbolic color '") + color + "' not known, or color does not begin with #");
|
||||
}
|
||||
if (std::string::npos != basecolor.find_first_not_of("0123456789abcdefABCDEF",1)) {
|
||||
}
|
||||
else { // Html color notation
|
||||
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])");
|
||||
}
|
||||
if (alpha) {
|
||||
if (basecolor.length() != 4 && basecolor.length() != 5 && basecolor.length() != 7 && basecolor.length() != 9)
|
||||
if (basecolor.length() != 4 && basecolor.length() != 5 && basecolor.length() != 7 && basecolor.length() != 9) {
|
||||
throw std::runtime_error(std::string("Color '") + color + "' not in the expected format (#xxx, #xxxx, #xxxxxx or #xxxxxxxx)");
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (basecolor.length() == 5 || basecolor.length() == 9)
|
||||
if (basecolor.length() == 5 || basecolor.length() == 9) {
|
||||
throw std::runtime_error(std::string("Color '") + color + "' not in the expected format (#xxx or #xxxxxx) - alpha not allowed");
|
||||
if (basecolor.length() != 4 && basecolor.length() != 7)
|
||||
}
|
||||
if (basecolor.length() != 4 && basecolor.length() != 7) {
|
||||
throw std::runtime_error(std::string("Color '") + color + "' not in the expected format (#xxx or #xxxxxx)");
|
||||
}
|
||||
}
|
||||
unsigned col = strtoul(basecolor.c_str() + 1, NULL, 16);
|
||||
unsigned col = strtoul(basecolor.c_str() + 1, nullptr, 16);
|
||||
if (basecolor.length() < 6) {
|
||||
if (basecolor.length() == 5)
|
||||
if (basecolor.length() == 5) {
|
||||
a = (col >> 12) & 0x0f;
|
||||
else
|
||||
}
|
||||
else {
|
||||
a = 0x0f;
|
||||
}
|
||||
a |= a << 4;
|
||||
r = (col >> 8) & 0x0f;
|
||||
r |= r << 4;
|
||||
|
@ -93,32 +101,38 @@ Color::Color(std::string color, int alpha)
|
|||
b |= b << 4;
|
||||
}
|
||||
else {
|
||||
if (basecolor.length() == 9)
|
||||
if (basecolor.length() == 9) {
|
||||
a = (col >> 24) & 0xff;
|
||||
else
|
||||
}
|
||||
else {
|
||||
a = 0xff;
|
||||
}
|
||||
r = (col >> 16) & 0xff;
|
||||
g = (col >> 8) & 0xff;
|
||||
b = (col >> 0) & 0xff;
|
||||
}
|
||||
if (alpha <= 0)
|
||||
if (alpha <= 0) {
|
||||
a = 0xff;
|
||||
} while(false);
|
||||
if (colormod.length() == 0)
|
||||
}
|
||||
}
|
||||
if (colormod.length() == 0) {
|
||||
return;
|
||||
}
|
||||
std::istringstream iss(colormod);
|
||||
iss >> std::ws;
|
||||
while (!iss.eof()) {
|
||||
double w;
|
||||
char operation;
|
||||
char ccode='w';
|
||||
char ccode = 'w';
|
||||
iss >> operation;
|
||||
iss >> ccode;
|
||||
iss >> w >> std::ws;
|
||||
if (w > 1)
|
||||
if (w > 1) {
|
||||
w = w / 255;
|
||||
if (!strchr("+-",operation) || !strchr("wkrgbcmy", ccode) || w < 0 || w > 1 || iss.fail())
|
||||
}
|
||||
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
|
||||
|
@ -126,53 +140,81 @@ Color::Color(std::string color, int alpha)
|
|||
int mixg = g;
|
||||
int mixb = b;
|
||||
if (operation == '+') {
|
||||
if (ccode == 'w')
|
||||
if (ccode == 'w') {
|
||||
mixr = mixg = mixb = 255;
|
||||
else if (operation == 'k')
|
||||
}
|
||||
else if (operation == 'k') {
|
||||
mixr = mixg = mixb = 0;
|
||||
else if (ccode == 'r')
|
||||
}
|
||||
else if (ccode == 'r') {
|
||||
mixr = 255;
|
||||
else if (ccode == 'g')
|
||||
}
|
||||
else if (ccode == 'g') {
|
||||
mixg = 255;
|
||||
else if (ccode == 'b')
|
||||
}
|
||||
else if (ccode == 'b') {
|
||||
mixb = 255;
|
||||
else if (ccode == 'c')
|
||||
}
|
||||
else if (ccode == 'c') {
|
||||
mixg = mixb = 255;
|
||||
else if (ccode == 'm')
|
||||
}
|
||||
else if (ccode == 'm') {
|
||||
mixr = mixb = 255;
|
||||
else if (ccode == 'y')
|
||||
}
|
||||
else if (ccode == 'y') {
|
||||
mixr = mixg = 255;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (ccode == 'w')
|
||||
if (ccode == 'w') {
|
||||
mixr = mixg = mixb = 0;
|
||||
else if (operation == 'k')
|
||||
}
|
||||
else if (operation == 'k') {
|
||||
mixr = mixg = mixb = 255;
|
||||
else if (ccode == 'r')
|
||||
}
|
||||
else if (ccode == 'r') {
|
||||
mixr = 0;
|
||||
else if (ccode == 'g')
|
||||
}
|
||||
else if (ccode == 'g') {
|
||||
mixg = 0;
|
||||
else if (ccode == 'b')
|
||||
}
|
||||
else if (ccode == 'b') {
|
||||
mixb = 0;
|
||||
else if (ccode == 'c')
|
||||
}
|
||||
else if (ccode == 'c') {
|
||||
mixg = mixb = 0;
|
||||
else if (ccode == 'm')
|
||||
}
|
||||
else if (ccode == 'm') {
|
||||
mixr = mixb = 0;
|
||||
else if (ccode == 'y')
|
||||
}
|
||||
else if (ccode == 'y') {
|
||||
mixr = mixg = 0;
|
||||
}
|
||||
}
|
||||
|
||||
v = r * (1 - w) + mixr * w;
|
||||
if (v < 0) v = 0;
|
||||
else if (v > 255) v = 255;
|
||||
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;
|
||||
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;
|
||||
if (v < 0) {
|
||||
v = 0;
|
||||
}
|
||||
else if (v > 255) {
|
||||
v = 255;
|
||||
}
|
||||
b = int(v + 0.5);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,23 +1,22 @@
|
|||
#pragma once
|
||||
|
||||
#ifndef COLOR_H
|
||||
#define COLOR_H
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
struct Color {
|
||||
Color(): r(0), g(0), b(0), a(0) {};
|
||||
Color() = default;
|
||||
Color(uint32_t c): r((c >> 16) & 0xff), g((c >> 8) & 0xff), b((c >> 0) & 0xff ), a((c >> 24) & 0xff) {};
|
||||
Color(uint8_t r, uint8_t g, uint8_t b): r(r), g(g), b(b), a(0xff) {};
|
||||
Color(uint8_t r, uint8_t g, uint8_t b, uint8_t a): r(r), g(g), b(b), a(a) {};
|
||||
Color(std::string s, int alpha = 1);
|
||||
Color &operator=(const Color &c);
|
||||
Color(const std::string& color, int alpha = 1);
|
||||
Color &operator=(const Color &c) = default;
|
||||
unsigned to_uint() const { return (unsigned(a) << 24) + (unsigned(r) << 16) + (unsigned(g) << 8) + unsigned(b); }
|
||||
//libgd treats 127 as transparent, and 0 as opaque ...
|
||||
int to_libgd() const { return (((0xff - int(a)) >> 1) << 24) + (int(r) << 16) + (int(g) << 8) + int(b); }
|
||||
uint8_t r;
|
||||
uint8_t g;
|
||||
uint8_t b;
|
||||
uint8_t a;
|
||||
uint8_t r{0};
|
||||
uint8_t g{0};
|
||||
uint8_t b{0};
|
||||
uint8_t a{0};
|
||||
};
|
||||
|
||||
struct ColorEntry {
|
||||
|
@ -26,31 +25,20 @@ struct ColorEntry {
|
|||
FlagIgnore = 0x01,
|
||||
FlagAir = 0x02,
|
||||
};
|
||||
ColorEntry(): r(0), g(0), b(0), a(0), t(0), f(0) {};
|
||||
ColorEntry() = default;
|
||||
ColorEntry(uint8_t r, uint8_t g, uint8_t b, uint8_t a, uint8_t t, uint8_t f): r(r), g(g), b(b), a(a), t(t), f(f) {};
|
||||
inline Color to_color() const { return Color(r, g, b, a); }
|
||||
uint8_t r;
|
||||
uint8_t g;
|
||||
uint8_t b;
|
||||
uint8_t a;
|
||||
uint8_t t;
|
||||
uint8_t f;
|
||||
uint8_t r{0};
|
||||
uint8_t g{0};
|
||||
uint8_t b{0};
|
||||
uint8_t a{0};
|
||||
uint8_t t{0};
|
||||
uint8_t f{0};
|
||||
};
|
||||
|
||||
inline Color &Color::operator=(const Color &c)
|
||||
{
|
||||
r = c.r;
|
||||
g = c.g;
|
||||
b = c.b;
|
||||
a = c.a;
|
||||
return *this;
|
||||
}
|
||||
|
||||
struct HeightMapColor
|
||||
{
|
||||
HeightMapColor(int h0, Color c0, int h1, Color c1) : height{ h0, h1 }, color{ c0, c1 } {}
|
||||
int height[2];
|
||||
Color color[2];
|
||||
};
|
||||
|
||||
#endif // COLOR_H
|
||||
|
|
Loading…
Reference in New Issue