colour: add html-style colour parsing

This commit is contained in:
Danny Robson 2017-05-22 16:20:21 +10:00
parent 813600e774
commit 30fa4a378d
3 changed files with 96 additions and 5 deletions

View File

@ -16,19 +16,56 @@
#include "./colour.hpp"
#include "./ascii.hpp"
#include "./debug.hpp"
#include "./log.hpp"
#include "./range.hpp"
#include <array>
#include <map>
//-----------------------------------------------------------------------------
///////////////////////////////////////////////////////////////////////////////
using util::colour;
using util::colour3f;
using util::colour4f;
//-----------------------------------------------------------------------------
///////////////////////////////////////////////////////////////////////////////
template <size_t S, typename T>
colour<S,T>
colour<S,T>::parse_html (const char *fmt)
{
// ensure the format is the correct length
auto len = strlen (fmt);
switch (len) {
case 1 + 2 * S:
if (*fmt != '#')
throw std::invalid_argument ("missing leading hash");
++fmt;
break;
case 2 * S:
break;
default:
throw std::invalid_argument ("format is the wrong length");
}
// parse the octets
util::colour<S,uint8_t> res;
for (size_t i = 0; i < res.size (); ++i) {
auto a = util::ascii::from_hex (fmt[i*2+0]);
auto b = util::ascii::from_hex (fmt[i*2+1]);
res[i] = (a << 4u) | b;
}
return res.template cast<T> ();
}
///////////////////////////////////////////////////////////////////////////////
static const std::map<std::string, colour<4,uint8_t>>
HTML_COLOURS { {
{ "white", { 0xff, 0xff, 0xff, 0xff } },

View File

@ -34,9 +34,22 @@ namespace util {
colour<S,U>
cast (void) const;
static colour from_html (const std::string&);
static colour from_x11 (const std::string&);
static colour from_string (const std::string&);
/// parse colours specified as "#AABBCCDD".
///
/// * the leading hash is optional.
/// * all components must be 2 hex digits.
static colour parse_html (const char*);
static colour parse_html (const std::string&);
/// look up the name of a colour from those specified in
/// html/x11/etc specifications.
static colour from_html (const std::string &name);
static colour from_x11 (const std::string &name);
/// look up all the specifications and returns the colour from one
/// that matches. the search order is unspecified, so if you want a
/// known colour then try them first yourself.
static colour from_string (const std::string &name);
};
// Convenience types

View File

@ -16,6 +16,47 @@ main (int, char**)
tap.expect_eq (u.cast<float> (), f, "cast u8 to float");
}
// Check parsing is working
tap.expect_eq (
util::colour4u::parse_html ("#11223344"),
util::colour4u (0x11, 0x22, 0x33, 0x44),
"4-component html parsing with hash"
);
tap.expect_eq (
util::colour4u::parse_html ("11223344"),
util::colour4u (0x11, 0x22, 0x33, 0x44),
"4-component html parsing without hash"
);
tap.expect_eq (
util::colour1f::parse_html ("ff"),
util::colour1f (1.f),
"1-component html parsing"
);
tap.expect_eq (
util::colour3u::parse_html ("3399ff"),
util::colour3u (0x33, 0x99, 0xff),
"3-component html parsing"
);
tap.expect_throw<std::invalid_argument> (
[] () { util::colour1f::parse_html ("00112233"); },
"1-component parsing with 4-component format"
);
tap.expect_throw<std::invalid_argument> (
[] () { util::colour4f::parse_html ("00"); },
"4-component parsing with 1-component format"
);
tap.expect_throw<std::invalid_argument> (
[] () { util::colour4f::parse_html ("0011223"); },
"4-component parsing with one too few digits"
);
// Check lookups are working
tap.expect_eq (util::colour4f::from_html ("white"), util::colour4f {1}, "HTML lookup");
tap.expect_eq ( util::colour4f::from_x11 ("white"), util::colour4f {1}, "X11 lookup");