Bridges-C++  3.4.5-dev1-6-g935685a
Bridges(C++ API)
Color.h
Go to the documentation of this file.
1 #ifndef COLOR_H
2 #define COLOR_H
3 
4 #include <iostream> //cerr
5 #include <array> //array
6 #include <regex> //regex
7 #include <unordered_map> //unordered_map
8 #include <cmath> //log
9 
10 #include <sstream>
11 #include <iomanip>
12 
13 #include "DataStructure.h" //string, using std
14 #include <JSONutil.h>
15 
16 namespace bridges {
17  namespace datastructure {
50  class Color {
51  private:
52  // The named colors' rgba channel value mappings
53  static const unordered_map<string, const array<int, 4 >> &
54  ColorNames() {
55  static unordered_map<string, const array<int, 4 >> cn {
56 
57  { {"aliceblue", {{240, 248, 255, 255}}},
58  {"antiquewhite", {{250, 235, 215, 255}}},
59  {"cyan", {{0, 255, 255, 255}}},
60  {"aquamarine", {{127, 255, 212, 255}}},
61  {"azure", {{240, 255, 255, 255}}},
62  {"beige", {{245, 245, 220, 255}}},
63  {"bisque", {{255, 228, 196, 255}}},
64  {"black", {{0, 0, 0, 255}}},
65  {"blanchedalmond", {{255, 235, 205, 255}}},
66  {"blue", {{0, 0, 255, 255}}},
67  {"blueviolet", {{138, 43, 226, 255}}},
68  {"brown", {{165, 42, 42, 255}}},
69  {"burlywood", {{222, 184, 135, 255}}},
70  {"cadetblue", {{95, 158, 160, 255}}},
71  {"chartreuse", {{127, 255, 0, 255}}},
72  {"chocolate", {{210, 105, 30, 255}}},
73  {"coral", {{255, 127, 80, 255}}},
74  {"cornflowerblue", {{100, 149, 237, 255}}},
75  {"cornsilk", {{255, 248, 220, 255}}},
76  {"crimson", {{220, 20, 60, 255}}},
77  {"darkblue", {{0, 0, 139, 255}}},
78  {"darkcyan", {{0, 139, 139, 255}}},
79  {"darkgoldenrod", {{184, 134, 11, 255}}},
80  {"darkgrey", {{169, 169, 169, 255}}},
81  {"darkgreen", {{0, 100, 0, 255}}},
82  {"darkkhaki", {{189, 183, 107, 255}}},
83  {"darkmagenta", {{139, 0, 139, 255}}},
84  {"darkolivegreen", {{85, 107, 47, 255}}},
85  {"darkorange", {{255, 140, 0, 255}}},
86  {"darkorchid", {{153, 50, 204, 255}}},
87  {"darkred", {{139, 0, 0, 255}}},
88  {"darksalmon", {{233, 150, 122, 255}}},
89  {"darkseagreen", {{143, 188, 143, 255}}},
90  {"darkslateblue", {{72, 61, 139, 255}}},
91  {"darkslategrey", {{47, 79, 79, 255}}},
92  {"darkturquoise", {{0, 206, 209, 255}}},
93  {"darkviolet", {{148, 0, 211, 255}}},
94  {"deeppink", {{255, 20, 147, 255}}},
95  {"deepskyblue", {{0, 191, 255, 255}}},
96  {"dimgrey", {{105, 105, 105, 255}}},
97  {"dodgerblue", {{30, 144, 255, 255}}},
98  {"firebrick", {{178, 34, 34, 255}}},
99  {"floralwhite", {{255, 250, 240, 255}}},
100  {"forestgreen", {{34, 139, 34, 255}}},
101  {"magenta", {{255, 0, 255, 255}}},
102  {"gainsboro", {{220, 220, 220, 255}}},
103  {"ghostwhite", {{248, 248, 255, 255}}},
104  {"gold", {{255, 215, 0, 255}}},
105  {"goldenrod", {{218, 165, 32, 255}}},
106  {"grey", {{128, 128, 128, 255}}},
107  {"green", {{0, 128, 0, 255}}},
108  {"greenyellow", {{173, 255, 47, 255}}},
109  {"honeydew", {{240, 255, 240, 255}}},
110  {"hotpink", {{255, 105, 180, 255}}},
111  {"indianred", {{205, 92, 92, 255}}},
112  {"indigo", {{75, 0, 130, 255}}},
113  {"ivory", {{255, 255, 240, 255}}},
114  {"khaki", {{240, 230, 140, 255}}},
115  {"lavender", {{230, 230, 250, 255}}},
116  {"lavenderblush", {{255, 240, 245, 255}}},
117  {"lawngreen", {{124, 252, 0, 255}}},
118  {"lemonchiffon", {{255, 250, 205, 255}}},
119  {"lightblue", {{173, 216, 230, 255}}},
120  {"lightcoral", {{240, 128, 128, 255}}},
121  {"lightcyan", {{224, 255, 255, 255}}},
122  {"lightgoldenrodyellow", {{250, 250, 210, 255}}},
123  {"lightgrey", {{211, 211, 211, 255}}},
124  {"lightgreen", {{144, 238, 144, 255}}},
125  {"lightpink", {{255, 182, 193, 255}}},
126  {"lightsalmon", {{255, 160, 122, 255}}},
127  {"lightseagreen", {{32, 178, 170, 255}}},
128  {"lightskyblue", {{135, 206, 250, 255}}},
129  {"lightslategrey", {{119, 136, 153, 255}}},
130  {"lightsteelblue", {{176, 196, 222, 255}}},
131  {"lightyellow", {{255, 255, 224, 255}}},
132  {"lime", {{0, 255, 0, 255}}},
133  {"limegreen", {{50, 205, 50, 255}}},
134  {"linen", {{250, 240, 230, 255}}},
135  {"maroon", {{128, 0, 0, 255}}},
136  {"mediumaquamarine", {{102, 205, 170, 255}}},
137  {"mediumblue", {{0, 0, 205, 255}}},
138  {"mediumorchid", {{186, 85, 211, 255}}},
139  {"mediumpurple", {{147, 112, 219, 255}}},
140  {"mediumseagreen", {{60, 179, 113, 255}}},
141  {"mediumslateblue", {{123, 104, 238, 255}}},
142  {"mediumspringgreen", {{0, 250, 154, 255}}},
143  {"mediumturquoise", {{72, 209, 204, 255}}},
144  {"mediumvioletred", {{199, 21, 133, 255}}},
145  {"midnightblue", {{25, 25, 112, 255}}},
146  {"mintcream", {{245, 255, 250, 255}}},
147  {"mistyrose", {{255, 228, 225, 255}}},
148  {"moccasin", {{255, 228, 181, 255}}},
149  {"navajowhite", {{255, 222, 173, 255}}},
150  {"navy", {{0, 0, 128, 255}}},
151  {"oldlace", {{253, 245, 230, 255}}},
152  {"olive", {{128, 128, 0, 255}}},
153  {"olivedrab", {{107, 142, 35, 255}}},
154  {"orange", {{255, 165, 0, 255}}},
155  {"orangered", {{255, 69, 0, 255}}},
156  {"orchid", {{218, 112, 214, 255}}},
157  {"palegoldenrod", {{238, 232, 170, 255}}},
158  {"palegreen", {{152, 251, 152, 255}}},
159  {"paleturquoise", {{175, 238, 238, 255}}},
160  {"palevioletred", {{219, 112, 147, 255}}},
161  {"papayawhip", {{255, 239, 213, 255}}},
162  {"peachpuff", {{255, 218, 185, 255}}},
163  {"peru", {{205, 133, 63, 255}}},
164  {"pink", {{255, 192, 203, 255}}},
165  {"plum", {{221, 160, 221, 255}}},
166  {"powderblue", {{176, 224, 230, 255}}},
167  {"purple", {{128, 0, 128, 255}}},
168  {"red", {{255, 0, 0, 255}}},
169  {"rosybrown", {{188, 143, 143, 255}}},
170  {"royalblue", {{65, 105, 225, 255}}},
171  {"saddlebrown", {{139, 69, 19, 255}}},
172  {"salmon", {{250, 128, 114, 255}}},
173  {"sandybrown", {{244, 164, 96, 255}}},
174  {"seagreen", {{46, 139, 87, 255}}},
175  {"seashell", {{255, 245, 238, 255}}},
176  {"sienna", {{160, 82, 45, 255}}},
177  {"silver", {{192, 192, 192, 255}}},
178  {"skyblue", {{135, 206, 235, 255}}},
179  {"slateblue", {{106, 90, 205, 255}}},
180  {"slategrey", {{112, 128, 144, 255}}},
181  {"snow", {{255, 250, 250, 255}}},
182  {"springgreen", {{0, 255, 127, 255}}},
183  {"steelblue", {{70, 130, 180, 255}}},
184  {"tan", {{210, 180, 140, 255}}},
185  {"teal", {{0, 128, 128, 255}}},
186  {"thistle", {{216, 191, 216, 255}}},
187  {"tomato", {{255, 99, 71, 255}}},
188  {"turquoise", {{64, 224, 208, 255}}},
189  {"violet", {{238, 130, 238, 255}}},
190  {"wheat", {{245, 222, 179, 255}}},
191  {"white", {{255, 255, 255, 255}}},
192  {"whitesmoke", {{245, 245, 245, 255}}},
193  {"yellow", {{255, 255, 0, 255}}},
194  {"yellowgreen", {{154, 205, 50, 255}}}
195  }
196  };
197  return cn;
198  }
199 
200  // The rgba channel values of this Color
201  array<int, 4> channels{{255, 255, 255, 255}};
202  public:
207  Color() {
208  setRed(0);
209  setGreen(0);
210  setBlue(0);
211  setAlpha(255);
212  }
222  Color(const int r, const int g, const int b, const int a = 255) {
223  setValue(r, g, b, a);
224  }
232  Color(const string& name) {
233  setValue(name);
234  }
239  bool operator==(const Color& that) const {
240  return channels == that.channels;
241  }
246  bool operator!=(const Color& that) const {
247  return channels != that.channels;
248  }
250  bool isOpaque() const {
251  return getAlpha() == 255;
252  }
257  bool isTransparent() const {
258  return getAlpha() == 0;
259  }
260 
265  int getRed() const {
266  return channels.at(0);
267  }
272  int getGreen() const {
273  return channels.at(1);
274  }
279  int getBlue() const {
280  return channels.at(2);
281  }
286  int getAlpha() const {
287  return channels.at(3);
288  }
289 
291  string getHexValue() const {
292  std::stringstream ss;
293  ss << "#";
294  ss << std::hex << std::setfill('0') << std::setw(2) << getRed();
295  ss << std::hex << std::setfill('0') << std::setw(2) << getGreen();
296  ss << std::hex << std::setfill('0') << std::setw(2) << getBlue();
297  ss << std::hex << std::setfill('0') << std::setw(2) << getAlpha();
298 
299  return ss.str();
300  }
305  void setRed(int r) {
306  setChannel(r, 0);
307  }
312  void setGreen(int g) {
313  setChannel(g, 1);
314  }
319  void setBlue(int b) {
320  setChannel(b, 2);
321  }
326  void setAlpha(int a) {
327  setChannel(a, 3);
328  }
329 
339  void setValue(int r, int g, int b, int a = 255) {
340  setRed(r);
341  setGreen(g);
342  setBlue(b);
343  setAlpha(a);
344  }
353  void setValue(string name) {
354  //marking static to avoid rebuilding the regexp every time.
355  //greedy, so checks for 8(RRGGBBAA), then 6(RRGGBB) then 4(RGBA) then 3(RGB)
356  static const regex HEX_RANGE("^#([[:xdigit:]]{8}|[[:xdigit:]]{6}|[[:xdigit:]]{3,4})$");
357 
358  for (char& c : name) {
359  c = (char) tolower((unsigned char)c); //convert to lowercase
360  }
361  auto it = ColorNames().find(name);
362 
363  if (it != ColorNames().end()) {
364  channels = it->second; //Named value
365  }
366  else if (regex_match(name, HEX_RANGE)) { //#Hex value
367  name.erase(0, 1); //removes "#"
368  // alpha value, overwritten if present by loop number
369  // of chars representing a channel
370  channels.at(3) = 255;
371  const int chanChars = (name.size() == 3 || name.size() == 4) ? 1 : 2;
372  //unit place scale factor, handles channel size variance
373  const int chanMultiplier = (chanChars == 1) ? 17 : 1;
374  for (size_t i = 0; i < name.size() / chanChars; i++) {
375  //converts and save hex val to rgba val
376  channels.at(i) = (int) strtol(name.substr(i * chanChars,
377  chanChars).c_str(), nullptr, 16) * chanMultiplier;
378  }
379  }
380  else { //invalid color
381  string errStr = "Invalid Color: " + name + "\nMust be a hexadecimal(#RRGGBBAA, #RRGGBB, #RGBA, or #RGB) color representation\nOr one of these supported named colors: ";
382  for (const auto& p : ColorNames()) {
383  errStr += " \"" + p.first + "\"";
384  }
385  errStr += "\n";
386  throw errStr;
387  }
388  }
389  const string getRepresentation () const {
390  return string(
391  "[" + to_string(getRed()) + "," +
392  to_string(getGreen()) + "," +
393  to_string(getBlue()) + "," +
394  to_string(getAlpha()) +
395  "]");
396  }
403  const string getCSSRepresentation() const {
405  if (this->isTransparent()) {
406  //leaves off other channels if transparent
407  return "[0, 0, 0, 0.0]";
408  }
409  const string strCSS =
410  JSONencode(this->getRed()) + "," +
411  JSONencode(this->getGreen()) + "," +
412  JSONencode(this->getBlue()) + "," +
413  JSONencode( ((float) (this->getAlpha()) / 255.0f));
414 
415  return OPEN_BOX + strCSS + CLOSE_BOX;
416  }
417  const void getCSSRepresentation(rapidjson::Document& d) const {
418 
419 
420  using namespace rapidjson;
421  double r = 0, g = 0, b = 0, alpha = 0;
422  Value v;
423  d.SetObject();
424  Document::AllocatorType& allocator = d.GetAllocator();
425  Value col_arr(kArrayType);
426  if (this->isTransparent()) {
427  //leaves off other channels if transparent
428  // d.AddMember("color", v.SetString("[0, 0, 0, 0]"),
429  // allocator);
430  col_arr.PushBack(0., allocator);
431  col_arr.PushBack(0., allocator);
432  col_arr.PushBack(0., allocator);
433  col_arr.PushBack(0., allocator);
434  }
435  else {
436  col_arr.PushBack(v.SetDouble(this->getRed()), allocator);
437  col_arr.PushBack(v.SetDouble(this->getGreen()), allocator);
438  col_arr.PushBack(v.SetDouble(this->getBlue()), allocator);
439  col_arr.PushBack(v.SetDouble(this->getAlpha()), allocator);
440  }
441  d.AddMember("color", col_arr, allocator);
442  }
443 
444  private:
445 
453  void setChannel(const int& value, const int& channel) {
454  (value < 0 || 255 < value)
455  ? throw "Invalid channel parameter: " + to_string(value) +
456  " Must be in the [0,255] range"
457  : channels.at(channel) = value;
458  }
459  };//end of color class
460  }
461 };//end of bridge namespace
462 #endif
This class represents Color, and supports rgba, hexadecimal and named color values.
Definition: Color.h:50
int getAlpha() const
Definition: Color.h:286
int getBlue() const
Definition: Color.h:279
void setAlpha(int a)
Definition: Color.h:326
const string getRepresentation() const
Definition: Color.h:389
bool operator==(const Color &that) const
Definition: Color.h:239
void setRed(int r)
Definition: Color.h:305
string getHexValue() const
Definition: Color.h:291
int getGreen() const
Definition: Color.h:272
const void getCSSRepresentation(rapidjson::Document &d) const
Definition: Color.h:417
Color(const int r, const int g, const int b, const int a=255)
Definition: Color.h:222
int getRed() const
Definition: Color.h:265
bool isTransparent() const
Definition: Color.h:257
void setBlue(int b)
Definition: Color.h:319
Color(const string &name)
Definition: Color.h:232
void setValue(int r, int g, int b, int a=255)
Definition: Color.h:339
bool operator!=(const Color &that) const
Definition: Color.h:246
const string getCSSRepresentation() const
Definition: Color.h:403
void setGreen(int g)
Definition: Color.h:312
bool isOpaque() const
Definition: Color.h:250
Color()
Definition: Color.h:207
void setValue(string name)
Definition: Color.h:353
std::string JSONencode(const T &d)
Definition: JSONutil.h:38
Support for drawing Bar charts.
Definition: alltypes.h:4
const string OPEN_BOX
Definition: DataStructure.h:55
const string CLOSE_BOX
Definition: DataStructure.h:56