Lumitronix_Iflex_Pro_Workshop
Library to interact with the iFlexPro
HtmlColor.h
Go to the documentation of this file.
1 /*-------------------------------------------------------------------------
2 HtmlColor provides a color object that can be directly consumed by LumitronixIFlexBus
3 
4 Written by Michael C. Miller.
5 
6 I invest time and resources providing this open source code,
7 please support me by dontating (see https://github.com/Makuna)
8 
9 -------------------------------------------------------------------------
10 This file is part of the LUMITRONIX_iFlex_Workshop library.
11 
12 LumitronixIFlexBus is free software: you can redistribute it and/or modify
13 it under the terms of the GNU Lesser General Public License as
14 published by the Free Software Foundation, either version 3 of
15 the License, or (at your option) any later version.
16 
17 LumitronixIFlexBus is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU Lesser General Public License for more details.
21 
22 You should have received a copy of the GNU Lesser General Public
23 License along with LumitronixIFlex. If not, see
24 <http://www.gnu.org/licenses/>.
25 -------------------------------------------------------------------------*/
26 #pragma once
27 
28 #define MAX_HTML_COLOR_NAME_LEN 21
29 
30 #ifndef pgm_read_ptr
31 // ESP8266 doesn't define this macro
32 #define pgm_read_ptr(addr) (*reinterpret_cast<const void* const *>(addr))
33 #endif
34 
35 // ------------------------------------------------------------------------
36 // HtmlColorPair represents an association between a name and a HTML color code
37 // ------------------------------------------------------------------------
39 {
40  PGM_P Name;
41  uint32_t Color;
42 };
43 
44 // ------------------------------------------------------------------------
45 // HtmlShortColorNames is a template class used for Parse and ToString
46 // ------------------------------------------------------------------------
48 {
49 public:
50  static const HtmlColorPair* Pair(uint8_t index);
51  static uint8_t Count();
52 };
53 
54 // ------------------------------------------------------------------------
55 // HtmlColorNames is a template class used for Parse and ToString
56 // ------------------------------------------------------------------------
58 {
59 public:
60  static const HtmlColorPair* Pair(uint8_t index);
61  static uint8_t Count();
62 };
63 
64 // ------------------------------------------------------------------------
65 // HtmlColor represents a color object that is represented by a single uint32
66 // value. It contains minimal routines and used primarily as a helper to
67 // initialize other color objects
68 // ------------------------------------------------------------------------
69 struct HtmlColor
70 {
71  // ------------------------------------------------------------------------
72  // Construct a HtmlColor using a single value (0-0xffffff)
73  // This works well for hexidecimal color definitions
74  // 0xff0000 = red, 0x00ff00 = green, and 0x0000ff = blue
75  // ------------------------------------------------------------------------
76  HtmlColor(uint32_t color) :
77  Color(color)
78  {
79  };
80 
81  // ------------------------------------------------------------------------
82  // Construct a HtmlColor using RgbColor
83  // ------------------------------------------------------------------------
84  HtmlColor(const RgbColor& color)
85  {
86  Color = static_cast<uint32_t>(color.R) << 16 | static_cast<uint32_t>(color.G) << 8 | static_cast<uint32_t>(color.B);
87  }
88 
89  // ------------------------------------------------------------------------
90  // Construct a HtmlColor that will have its values set in latter operations
91  // CAUTION: The Color member is not initialized and may not be consistent
92  // ------------------------------------------------------------------------
94  {
95  };
96 
97  // ------------------------------------------------------------------------
98  // Comparison operators
99  // ------------------------------------------------------------------------
100  bool operator==(const HtmlColor& other) const
101  {
102  return (Color == other.Color);
103  };
104 
105  bool operator!=(const HtmlColor& other) const
106  {
107  return !(*this == other);
108  };
109 
110  // ------------------------------------------------------------------------
111  // Parse a HTML4/CSS3 color name
112  // T_HTMLCOLORNAMES - template class that defines the collection of names
113  // name - the color name
114  // nameSize - the max size of name to check
115  //
116  // returns - zero if failed, or the number of chars parsed
117  //
118  // It will stop parsing name when a null terminator is reached,
119  // nameSize is reached, no match is found in the name/color pair table, or
120  // a non-alphanumeric is read like seperators or whitespace.
121  //
122  // It also accepts 3 or 6 digit hexadecimal notation (#rgb or #rrggbb),
123  // but it doesn't accept RGB, RGBA nor HSL values.
124  //
125  // See https://www.w3.org/TR/css3-color/#SRGB
126  //
127  // name must point to the first non-whitespace character to be parsed
128  // parsing will stop at the first non-alpha numeric
129  //
130  // Name MUST NOT be a PROGMEM pointer
131  //
132  // examples:
133  // Parse<HtmlShortColorNames>(buff, buffSize);
134  // Parse<HtmlColorNames>(buff, buffSize);
135  // ------------------------------------------------------------------------
136 
137  template <typename T_HTMLCOLORNAMES> size_t Parse(const char* name, size_t nameSize)
138  {
139  if (nameSize > 0)
140  {
141  if (name[0] == '#')
142  {
143  // Parse an hexadecimal notation "#rrbbgg" or "#rgb"
144  //
145  uint8_t temp[6]; // stores preconverted chars to hex values
146  uint8_t tempSize = 0;
147 
148  for (uint8_t indexChar = 1; indexChar < nameSize && indexChar < 8; ++indexChar)
149  {
150  char c = name[indexChar];
151  if (c >= '0' && c <= '9')
152  {
153  c -= '0';
154  }
155  else
156  {
157  // Convert a letter to lower case (only for ASCII letters)
158  // It's faster & smaller than tolower()
159  c |= 32;
160  if (c >= 'a' && c <= 'f')
161  {
162  c = c - 'a' + 10;
163  }
164  else
165  {
166  // we found an non hexidecimal char
167  // which could be null, deliminator, or other spacing
168  break;
169  }
170  }
171 
172  temp[tempSize] = c;
173  tempSize++;
174  }
175 
176  if (tempSize != 3 && tempSize != 6)
177  {
178  // invalid count of numerical chars
179  return 0;
180  }
181  else
182  {
183  uint32_t color = 0;
184  for (uint8_t indexChar = 0; indexChar < tempSize; ++indexChar)
185  {
186  color = color * 16 + temp[indexChar];
187  if (tempSize == 3)
188  {
189  // 3 digit hexadecimal notation can be supported easily
190  // duplicating digits.
191  color = color * 16 + temp[indexChar];
192  }
193  }
194 
195  Color = color;
196  return tempSize;
197  }
198  }
199  else
200  {
201  // parse a standard name for the color
202  //
203 
204  // the normal list is small enough a binary search isn't interesting,
205  for (uint8_t indexName = 0; indexName < T_HTMLCOLORNAMES::Count(); ++indexName)
206  {
207  const HtmlColorPair* colorPair = T_HTMLCOLORNAMES::Pair(indexName);
208  PGM_P searchName = reinterpret_cast<PGM_P>(pgm_read_ptr(&(colorPair->Name)));
209  size_t str1Size = nameSize;
210  const char* str1 = name;
211  const char* str2P = searchName;
212 
213  uint16_t result;
214 
215  while (str1Size > 0)
216  {
217  char ch1 = tolower(*str1++);
218  char ch2 = tolower(pgm_read_byte(str2P++));
219  result = ch1 - ch2;
220  if (result != 0 || ch2 == '\0')
221  {
222  if (ch2 == '\0' && !isalnum(ch1))
223  {
224  // the string continues but is not part of a
225  // valid color name,
226  // ends in white space, deliminator, etc
227  result = 0;
228  }
229  break;
230  }
231  result = -1; // have not reached the end of searchName;
232  str1Size--;
233  }
234 
235  if (result == 0)
236  {
237  Color = pgm_read_dword(&colorPair->Color);
238  return nameSize - str1Size;
239  }
240  }
241  }
242  }
243 
244  return 0;
245  }
246 
247  template <typename T_HTMLCOLORNAMES> size_t Parse(const char* name)
248  {
249  return Parse<T_HTMLCOLORNAMES>(name, MAX_HTML_COLOR_NAME_LEN + 1);
250  }
251 
252  template <typename T_HTMLCOLORNAMES> size_t Parse(String const &name)
253  {
254  return Parse<T_HTMLCOLORNAMES>(name.c_str(), name.length() + 1);
255  }
256 
257  // ------------------------------------------------------------------------
258  // Converts this color code to its HTML4/CSS3 name
259  // T_HTMLCOLORNAMES - template class that defines the collection of names
260  // buf - buffer to write the string
261  // bufSize - actual size of buf array
262  //
263  // It returns the number of chars required not including the NUL terminator.
264  //
265  // If there is not enough space in the buffer, it will write as many
266  // characters as allowed and will always finish the buffer with a NUL char
267  //
268  // examples:
269  // ToString<HtmlShortColorNames>(buf, bufSize);
270  // ToString<htmlColorNames>(buf, bufSize);
271  // ------------------------------------------------------------------------
272 
273  template <typename T_HTMLCOLORNAMES> size_t ToString(char* buf, size_t bufSize) const
274  {
275  // search for a color value/name pairs first
276  for (uint8_t indexName = 0; indexName < T_HTMLCOLORNAMES::Count(); ++indexName)
277  {
278  const HtmlColorPair* colorPair = T_HTMLCOLORNAMES::Pair(indexName);
279  if (pgm_read_dword(&colorPair->Color) == Color)
280  {
281  PGM_P name = (PGM_P)pgm_read_ptr(&colorPair->Name);
282  strncpy_P(buf, name, bufSize);
283  return strlen_P(name);
284  }
285  }
286 
287  // no color name pair match, convert using numerical format
288  return ToNumericalString(buf, bufSize);
289  }
290 
291  // ------------------------------------------------------------------------
292  // Converts this color code to its HTML4/CSS3 numerical name
293  //
294  // buf - buffer to write the string
295  // bufSize - actual size of buf array
296  //
297  // It returns the number of chars required not including the NUL terminator.
298  //
299  // If there is not enough space in the buffer, it will write as many
300  // characters as allowed and will always finish the buffer with a NUL char
301  // ------------------------------------------------------------------------
302 
303  size_t ToNumericalString(char* buf, size_t bufSize) const;
304 
305  // ------------------------------------------------------------------------
306  // BilinearBlend between four colors by the amount defined by 2d variable
307  // c00 - upper left quadrant color
308  // c01 - upper right quadrant color
309  // c10 - lower left quadrant color
310  // c11 - lower right quadrant color
311  // x - unit value (0.0 - 1.0) that defines the blend progress in horizontal space
312  // y - unit value (0.0 - 1.0) that defines the blend progress in vertical space
313  // ------------------------------------------------------------------------
314 
315  static HtmlColor BilinearBlend(const HtmlColor& c00,
316  const HtmlColor& c01,
317  const HtmlColor& c10,
318  const HtmlColor& c11,
319  float x,
320  float y)
321  {
322  return RgbColor::BilinearBlend(c00, c01, c10, c11, x, y);
323  }
324 
325  // ------------------------------------------------------------------------
326  // Color member (0-0xffffff) where
327  // 0xff0000 is red
328  // 0x00ff00 is green
329  // 0x0000ff is blue
330  // ------------------------------------------------------------------------
331  uint32_t Color;
332 };
333 
#define pgm_read_ptr(addr)
Definition: HtmlColor.h:32
#define MAX_HTML_COLOR_NAME_LEN
Definition: HtmlColor.h:28
Definition: HtmlColor.h:58
static uint8_t Count()
Definition: HtmlColorNames.cpp:191
static const HtmlColorPair * Pair(uint8_t index)
Definition: HtmlColorNames.cpp:186
Definition: HtmlColor.h:48
static uint8_t Count()
Definition: HtmlColorShortNames.cpp:62
static const HtmlColorPair * Pair(uint8_t index)
Definition: HtmlColorShortNames.cpp:57
Definition: HtmlColor.h:39
uint32_t Color
Definition: HtmlColor.h:41
PGM_P Name
Definition: HtmlColor.h:40
Definition: HtmlColor.h:70
size_t ToString(char *buf, size_t bufSize) const
Definition: HtmlColor.h:273
bool operator!=(const HtmlColor &other) const
Definition: HtmlColor.h:105
size_t ToNumericalString(char *buf, size_t bufSize) const
Definition: HtmlColor.cpp:39
size_t Parse(const char *name, size_t nameSize)
Definition: HtmlColor.h:137
uint32_t Color
Definition: HtmlColor.h:331
bool operator==(const HtmlColor &other) const
Definition: HtmlColor.h:100
HtmlColor(const RgbColor &color)
Definition: HtmlColor.h:84
size_t Parse(String const &name)
Definition: HtmlColor.h:252
HtmlColor()
Definition: HtmlColor.h:93
size_t Parse(const char *name)
Definition: HtmlColor.h:247
static HtmlColor BilinearBlend(const HtmlColor &c00, const HtmlColor &c01, const HtmlColor &c10, const HtmlColor &c11, float x, float y)
Definition: HtmlColor.h:315
HtmlColor(uint32_t color)
Definition: HtmlColor.h:76
Definition: RgbColor.h:36
uint8_t G
Definition: RgbColor.h:247
uint8_t B
Definition: RgbColor.h:248
uint8_t R
Definition: RgbColor.h:246
static RgbColor BilinearBlend(const RgbColor &c00, const RgbColor &c01, const RgbColor &c10, const RgbColor &c11, float x, float y)
Definition: RgbColor.cpp:181