Added color_utils
This commit is contained in:
@ -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
30
src/color_utils.cpp
Normal 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
143
src/color_utils.h
Normal 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
|
@ -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...
|
||||
|
@ -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);
|
||||
|
Reference in New Issue
Block a user