Added color_utils

This commit is contained in:
2021-08-06 21:54:08 +02:00
parent b12426ffee
commit a436aef990
5 changed files with 200 additions and 28 deletions

View File

@ -1,13 +1,14 @@
set(headers
src/cleanuphelper.h
src/color_utils.h
src/cppbitmask.h
src/crc32builder.h
src/cppflags.h
src/cppmacros.h
src/cppoverloadutils.h
src/cppsignal.h
src/cpptypesafeenum.h
src/cpputils.h
src/crc32builder.h
src/delayedconstruction.h
src/numberparsing.h
src/refwhenneeded.h
@ -15,6 +16,7 @@ set(headers
)
set(sources
src/color_utils.cpp
src/strutils.cpp
)

30
src/color_utils.cpp Normal file
View File

@ -0,0 +1,30 @@
#include "color_utils.h"
// 3rdparty lib includes
#include <fmt/core.h>
namespace cpputils {
std::string toString(ColorHelper color)
{
return fmt::format("#{:02X}{:02X}{:02X}", color.r, color.g, color.b);
}
tl::expected<ColorHelper, std::string> parseColor(std::string_view str)
{
// input may be "#FFF" or "#FFFFFF" or "#FFFFFFFF"
if (ColorHelper helper; std::sscanf(str.data(), "#%2hhx%2hhx%2hhx", &helper.r, &helper.g, &helper.b) == 3)
return helper;
if (ColorHelper helper; std::sscanf(str.data(), "#%1hhx%1hhx%1hhx", &helper.r, &helper.g, &helper.b) == 3)
{
helper.r <<= 4;
helper.g <<= 4;
helper.b <<= 4;
return helper;
}
return tl::make_unexpected(fmt::format("invalid color {}", str));
}
} // namespace cpputils

143
src/color_utils.h Normal file
View File

@ -0,0 +1,143 @@
#pragma once
// system includes
#include <string>
#include <string_view>
#include <array>
// 3rdparty lib includes
#include <tl/expected.hpp>
namespace cpputils {
struct ColorHelper
{
constexpr ColorHelper() = default;
constexpr ColorHelper(uint8_t _r, uint8_t _g, uint8_t _b) : r{_r}, g{_g}, b{_b} {}
constexpr ColorHelper(const ColorHelper &other) = default;
constexpr ColorHelper &operator=(const ColorHelper &other) = default;
constexpr bool operator==(const ColorHelper &other) const { return r == other.r && g == other.g && b == other.b; }
constexpr bool operator!=(const ColorHelper &other) const { return r != other.r || g != other.g || b != other.b; }
uint8_t r{};
uint8_t g{};
uint8_t b{};
};
namespace {
constexpr ColorHelper black{};
constexpr ColorHelper red{255, 0, 0};
constexpr ColorHelper blue{0, 0, 255};
constexpr ColorHelper yellow{255, 255, 0};
constexpr ColorHelper cyan{0, 255, 255};
constexpr ColorHelper green{0, 255, 0};
constexpr ColorHelper white{255, 255, 255};
constexpr ColorHelper pink{255, 0, 255};
} // namespace
struct HsvColor
{
constexpr HsvColor() = default;
constexpr HsvColor(uint8_t _h, uint8_t _s, uint8_t _v) : h{_h}, s{_s}, v{_v} {}
constexpr HsvColor(const HsvColor &other) = default;
constexpr HsvColor &operator=(const HsvColor &other) = default;
constexpr bool operator==(const HsvColor &other) const { return h == other.h && s == other.s && v == other.v; }
constexpr bool operator!=(const HsvColor &other) const { return h != other.h || s != other.s || v != other.v; }
uint8_t h{};
uint8_t s{};
uint8_t v{};
};
std::string toString(ColorHelper color);
tl::expected<ColorHelper, std::string> parseColor(std::string_view str);
inline uint32_t colorToNumber(ColorHelper color)
{
union {
uint32_t temp;
struct {
// reverse order to be reverse compatible with existing configs
uint8_t b;
uint8_t g;
uint8_t r;
uint8_t x;
};
} helper;
helper.b = color.b;
helper.g = color.g;
helper.r = color.r;
helper.x = 0;
return helper.temp;
}
inline ColorHelper numberToColor(uint32_t number)
{
union {
uint32_t temp;
struct {
// reverse order to be reverse compatible with existing configs
uint8_t b;
uint8_t g;
uint8_t r;
uint8_t x;
};
} helper;
helper.temp = number;
return ColorHelper{helper.r, helper.g, helper.b};
}
constexpr inline ColorHelper interpolateColor(ColorHelper left, ColorHelper right, uint8_t pos)
{
int16_t leftAmount = pos;
int16_t rightAmount = 255 - pos;
return ColorHelper (
(left.r * leftAmount / 255) + (right.r * rightAmount / 255),
(left.g * leftAmount / 255) + (right.g * rightAmount / 255),
(left.b * leftAmount / 255) + (right.b * rightAmount / 255)
);
}
constexpr inline ColorHelper HsvToRgb(HsvColor hsv)
{
if (hsv.s == 0)
return ColorHelper{hsv.v, hsv.v, hsv.v};
const uint8_t region = hsv.h / 43;
const uint8_t remainder = (hsv.h - (region * 43)) * 6;
const uint8_t p = (hsv.v * (255 - hsv.s)) >> 8;
const uint8_t q = (hsv.v * (255 - ((hsv.s * remainder) >> 8))) >> 8;
const uint8_t t = (hsv.v * (255 - ((hsv.s * (255 - remainder)) >> 8))) >> 8;
switch (region)
{
case 0: return ColorHelper{hsv.v, t, p };
case 1: return ColorHelper{q, hsv.v, p };
case 2: return ColorHelper{p, hsv.v, t };
case 3: return ColorHelper{p, q, hsv.v};
case 4: return ColorHelper{t, p, hsv.v};
default: return ColorHelper{hsv.v, p, q };
}
}
template<size_t COUNT>
constexpr inline std::array<ColorHelper, COUNT> generateRainbowColors()
{
std::array<ColorHelper, COUNT> colors;
for (int i = 0; i < COUNT; i++)
{
HsvColor hsvColor{uint8_t(i * 256.f / COUNT), 240, 255};
ColorHelper rgbColor = HsvToRgb(hsvColor);
colors[i] = rgbColor;
}
return colors;
}
} // namespace cpputils

View File

@ -5,20 +5,6 @@
#include <cctype>
namespace cpputils {
std::string toString(bool val) { return val ? "true" : "false"; }
std::string toString(int8_t val) { return std::to_string(val); }
std::string toString(uint8_t val) { return std::to_string(val); }
std::string toString(int16_t val) { return std::to_string(val); }
std::string toString(uint16_t val) { return std::to_string(val); }
std::string toString(int32_t val) { return std::to_string(val); }
std::string toString(uint32_t val) { return std::to_string(val); }
std::string toString(int64_t val) { return std::to_string(val); }
std::string toString(uint64_t val) { return std::to_string(val); }
std::string toString(float val) { return std::to_string(val); }
std::string toString(double val) { return std::to_string(val); }
std::string toString(const std::string &val) { return val; }
std::string toString(std::optional<uint8_t> val) { if (val) return toString(*val); else return {}; }
bool stringEqualsIgnoreCase(std::string_view a, std::string_view b)
{
return a == b; // HACK for now...

View File

@ -6,19 +6,30 @@
#include <string_view>
namespace cpputils {
std::string toString(bool val);
std::string toString(int8_t val);
std::string toString(uint8_t val);
std::string toString(int16_t val);
std::string toString(uint16_t val);
std::string toString(int32_t val);
std::string toString(uint32_t val);
std::string toString(int64_t val);
std::string toString(uint64_t val);
std::string toString(float val);
std::string toString(double val);
std::string toString(const std::string &val);
std::string toString(std::optional<uint8_t> val);
inline std::string toString(bool val) { return val ? "true" : "false"; }
inline std::string toString(int8_t val) { return std::to_string(val); }
inline std::string toString(uint8_t val) { return std::to_string(val); }
inline std::string toString(int16_t val) { return std::to_string(val); }
inline std::string toString(uint16_t val) { return std::to_string(val); }
inline std::string toString(int32_t val) { return std::to_string(val); }
inline std::string toString(uint32_t val) { return std::to_string(val); }
inline std::string toString(int64_t val) { return std::to_string(val); }
inline std::string toString(uint64_t val) { return std::to_string(val); }
inline std::string toString(float val) { return std::to_string(val); }
inline std::string toString(double val) { return std::to_string(val); }
inline std::string toString(const std::string &val) { return val; }
inline std::string toString(std::optional<bool> val) { if (val) return toString(*val); else return {}; }
inline std::string toString(std::optional<int8_t> val) { if (val) return toString(*val); else return {}; }
inline std::string toString(std::optional<uint8_t> val) { if (val) return toString(*val); else return {}; }
inline std::string toString(std::optional<int16_t> val) { if (val) return toString(*val); else return {}; }
inline std::string toString(std::optional<uint16_t> val) { if (val) return toString(*val); else return {}; }
inline std::string toString(std::optional<int32_t> val) { if (val) return toString(*val); else return {}; }
inline std::string toString(std::optional<uint32_t> val) { if (val) return toString(*val); else return {}; }
inline std::string toString(std::optional<int64_t> val) { if (val) return toString(*val); else return {}; }
inline std::string toString(std::optional<uint64_t> val) { if (val) return toString(*val); else return {}; }
inline std::string toString(std::optional<float> val) { if (val) return toString(*val); else return {}; }
inline std::string toString(std::optional<double> val) { if (val) return toString(*val); else return {}; }
inline std::string toString(const std::optional<std::string> &val) { if (val) return toString(*val); else return {}; }
bool stringEqualsIgnoreCase(std::string_view a, std::string_view b);
bool stringStartsWith(std::string_view fullString, std::string_view begin);