Skip to content

Commit

Permalink
Merge pull request #116 from Makuna/ExpandedColorStrings
Browse files Browse the repository at this point in the history
Refactored To Remove CSS3 define
  • Loading branch information
Makuna authored Jul 4, 2016
2 parents 05e3d13 + 7743a76 commit 929d4f7
Show file tree
Hide file tree
Showing 9 changed files with 792 additions and 484 deletions.
2 changes: 2 additions & 0 deletions keywords.txt
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@ NeoBufferProgmemMethod KEYWORD1
NeoBuffer KEYWORD1
NeoVerticalSpriteSheet KEYWORD1
NeoBitmapFile KEYWORD1
HtmlShortColorNames KEYWORD1
HtmlColorNames KEYWORD1

#######################################
# Methods and Functions (KEYWORD2)
Expand Down
2 changes: 1 addition & 1 deletion library.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"type": "git",
"url": "https://github.com/Makuna/NeoPixelBus"
},
"version": "2.1.3",
"version": "2.1.4",
"frameworks": "arduino",
"platforms": "*"
}
Expand Down
2 changes: 1 addition & 1 deletion library.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name=NeoPixelBus by Makuna
version=2.1.3
version=2.1.4
author=Michael C. Miller ([email protected])
maintainer=Michael C. Miller ([email protected])
sentence=A library that makes controlling NeoPixels (WS2811, WS2812 & SK6812) easy.
Expand Down
468 changes: 0 additions & 468 deletions src/internal/HtmlColor.cpp

Large diffs are not rendered by default.

197 changes: 183 additions & 14 deletions src/internal/HtmlColor.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,45 @@ License along with NeoPixel. If not, see
#include <Arduino.h>
#include "RgbColor.h"

// Due to Arduino's lack of Project settings for symbols, library code (c,cpp)
// files can't react to defines in sketch, so this must be defined here
// #define USE_CSS3_COLORS 1
#define MAX_HTML_COLOR_NAME_LEN 21

#ifndef pgm_read_ptr
// ESP8266 doesn't define this macro
#define pgm_read_ptr(addr) (*reinterpret_cast<const void* const *>(addr))
#endif

#ifndef countof
#define countof(array) (sizeof(array)/sizeof(array[0]))
#endif

// ------------------------------------------------------------------------
// HtmlColorPair represents an association between a name and a HTML color code
// ------------------------------------------------------------------------
struct HtmlColorPair
{
PGM_P Name;
uint32_t Color;
};

// ------------------------------------------------------------------------
// HtmlShortColorNames is a template class used for Parse and ToString
// ------------------------------------------------------------------------
class HtmlShortColorNames
{
public:
static const HtmlColorPair* Pair(uint8_t index);
static uint8_t Count();
};

// ------------------------------------------------------------------------
// HtmlColorNames is a template class used for Parse and ToString
// ------------------------------------------------------------------------
class HtmlColorNames
{
public:
static const HtmlColorPair* Pair(uint8_t index);
static uint8_t Count();
};

// ------------------------------------------------------------------------
// HtmlColor represents a color object that is represented by a single uint32
Expand Down Expand Up @@ -80,7 +116,7 @@ struct HtmlColor

// ------------------------------------------------------------------------
// Parse a HTML4/CSS3 color name
//
// T_HTMLCOLORNAMES - template class that defines the collection of names
// name - the color name
// nameSize - the max size of name to check
//
Expand All @@ -90,9 +126,6 @@ struct HtmlColor
// nameSize is reached, no match is found in the name/color pair table, or
// a non-alphanumeric is read like seperators or whitespace.
//
// It accepts all standard HTML4 names and, if USE_CSS3_COLORS macro is
// defined, the extended color names defined in CSS3 standard also.
//
// It also accepts 3 or 6 digit hexadecimal notation (#rgb or #rrggbb),
// but it doesn't accept RGB, RGBA nor HSL values.
//
Expand All @@ -102,31 +135,165 @@ struct HtmlColor
// parsing will stop at the first non-alpha numeric
//
// Name MUST NOT be a PROGMEM pointer
//
// examples:
// Parse<HtmlShortColorNames>(buff, buffSize);
// Parse<HtmlColorNames>(buff, buffSize);
// ------------------------------------------------------------------------
size_t Parse(const char* name, size_t nameSize);

size_t Parse(const char* name)
template <typename T_HTMLCOLORNAMES> size_t Parse(const char* name, size_t nameSize)
{
if (nameSize > 0)
{
if (name[0] == '#')
{
// Parse an hexadecimal notation "#rrbbgg" or "#rgb"
//
uint8_t temp[6]; // stores preconverted chars to hex values
uint8_t tempSize = 0;

for (uint8_t indexChar = 1; indexChar < nameSize && indexChar < 8; ++indexChar)
{
char c = name[indexChar];
if (c >= '0' && c <= '9')
{
c -= '0';
}
else
{
// Convert a letter to lower case (only for ASCII letters)
// It's faster & smaller than tolower()
c |= 32;
if (c >= 'a' && c <= 'f')
{
c = c - 'a' + 10;
}
else
{
// we found an non hexidecimal char
// which could be null, deliminator, or other spacing
break;
}
}

temp[tempSize] = c;
tempSize++;
}

if (tempSize != 3 && tempSize != 6)
{
// invalid count of numerical chars
return 0;
}
else
{
uint32_t color = 0;
for (uint8_t indexChar = 0; indexChar < tempSize; ++indexChar)
{
color = color * 16 + temp[indexChar];
if (tempSize == 3)
{
// 3 digit hexadecimal notation can be supported easily
// duplicating digits.
color = color * 16 + temp[indexChar];
}
}

Color = color;
return tempSize;
}
}
else
{
// parse a standard name for the color
//

// the normal list is small enough a binary search isn't interesting,
for (uint8_t indexName = 0; indexName < T_HTMLCOLORNAMES::Count(); ++indexName)
{
const HtmlColorPair* colorPair = T_HTMLCOLORNAMES::Pair(indexName);
PGM_P searchName = (PGM_P)pgm_read_ptr(&colorPair->Name);
size_t str1Size = nameSize;
const char* str1 = name;
const char* str2P = searchName;

uint16_t result;

while (str1Size > 0)
{
char ch1 = tolower(*str1++);
char ch2 = tolower(pgm_read_byte(str2P++));
result = ch1 - ch2;
if (result != 0 || ch2 == '\0')
{
if (ch2 == '\0' && !isalnum(ch1))
{
// the string continues but is not part of a
// valid color name,
// ends in white space, deliminator, etc
result = 0;
}
break;
}
result = -1; // have not reached the end of searchName;
str1Size--;
}

if (result == 0)
{
Color = pgm_read_dword(&colorPair->Color);
return nameSize - str1Size;
}
}
}
}

return 0;
}

template <typename T_HTMLCOLORNAMES> size_t Parse(const char* name)
{
return Parse(name, strlen(name) + 1);
return Parse<T_HTMLCOLORNAMES>(name, MAX_HTML_COLOR_NAME_LEN + 1);
}

size_t Parse(String const &name)
template <typename T_HTMLCOLORNAMES> size_t Parse(String const &name)
{
return Parse(name.c_str(), name.length() + 1);
return Parse<T_HTMLCOLORNAMES>(name.c_str(), name.length() + 1);
}

// ------------------------------------------------------------------------
// Converts this color code to its HTML4/CSS3 name
//
// T_HTMLCOLORNAMES - template class that defines the collection of names
// buf - buffer to write the string
// bufSize - actual size of buf array
//
// It returns the number of chars required not including the NUL terminator.
//
// If there is not enough space in the buffer, it will write as many
// characters as allowed and will always finish the buffer with a NUL char
//
// examples:
// ToString<HtmlShortColorNames>(buf, bufSize);
// ToString<htmlColorNames>(buf, bufSize);
// ------------------------------------------------------------------------
size_t ToString(char *buf, size_t bufSize) const;

template <typename T_HTMLCOLORNAMES> size_t ToString(char* buf, size_t bufSize) const
{
// search for a color value/name pairs first
for (uint8_t indexName = 0; indexName < T_HTMLCOLORNAMES::Count(); ++indexName)
{
const HtmlColorPair* colorPair = T_HTMLCOLORNAMES::Pair(indexName);
if (pgm_read_dword(&colorPair->Color) == Color)
{
PGM_P name = (PGM_P)pgm_read_ptr(&colorPair->Name);
strncpy_P(buf, name, bufSize);
return strlen_P(name);
}
}

// no color name pair match, convert using numerical format
return ToNumericalString(buf, bufSize);
}

// ------------------------------------------------------------------------
// Converts this color code to its HTML4/CSS3 numerical name
Expand All @@ -139,6 +306,7 @@ struct HtmlColor
// If there is not enough space in the buffer, it will write as many
// characters as allowed and will always finish the buffer with a NUL char
// ------------------------------------------------------------------------

size_t ToNumericalString(char* buf, size_t bufSize) const;

// ------------------------------------------------------------------------
Expand All @@ -150,6 +318,7 @@ struct HtmlColor
// x - unit value (0.0 - 1.0) that defines the blend progress in horizontal space
// y - unit value (0.0 - 1.0) that defines the blend progress in vertical space
// ------------------------------------------------------------------------

static HtmlColor BilinearBlend(const HtmlColor& c00,
const HtmlColor& c01,
const HtmlColor& c10,
Expand Down
Loading

0 comments on commit 929d4f7

Please sign in to comment.