11 struct std::hash<qx::color>
13 constexpr
size_t operator()(
const qx::color& color)
const noexcept
16 qx::hash_combine(nHash, color.
r());
17 qx::hash_combine(nHash, color.
g());
18 qx::hash_combine(nHash, color.
b());
19 qx::hash_combine(nHash, color.
a());
40 template<
class char_t>
45 #define _QX_ADD_COLOR(snakeCaseName, pascalCaseName, r, g, b) \
46 add(QX_STR_PREFIX(char_t, #snakeCaseName), color_name_type::css_snake, color(r, g, b)); \
47 add(QX_STR_PREFIX(char_t, #pascalCaseName), color_name_type::css_pascal, color(r, g, b));
76 std::optional<basic_string_view<char_t>>
get(
const color&
color, color_name_type eColorNameType)
const noexcept;
79 std::unordered_map<basic_string<char_t>,
color> m_StringToColor;
80 std::unordered_map<color, basic_string<char_t>> m_ColorToCssSnake;
81 std::unordered_map<color, basic_string<char_t>> m_ColorToCssPascal;
84 template<
class char_t>
90 template<
class char_t>
93 color_name_type eColorNameType,
96 if (eColorNameType == color_name_type::css_snake)
97 m_ColorToCssSnake[
color] = sName;
98 else if (eColorNameType == color_name_type::css_pascal)
99 m_ColorToCssPascal[
color] = sName;
101 m_StringToColor[sName] = std::move(
color);
104 template<
class char_t>
107 if (
const auto it = m_StringToColor.find(sName); it != m_StringToColor.end())
113 template<
class char_t>
116 color_name_type eColorNameType)
const noexcept
118 if (eColorNameType == color_name_type::css_snake)
120 if (
const auto it = m_ColorToCssSnake.find(
color); it != m_ColorToCssSnake.end())
123 else if (eColorNameType == color_name_type::css_pascal)
125 if (
const auto it = m_ColorToCssPascal.find(
color); it != m_ColorToCssPascal.end())
134 constexpr color::color(
float fRed,
float fGreen,
float fBlue,
float fAlpha) noexcept
136 assign_checked({ fRed, fGreen, fBlue, fAlpha });
139 constexpr color::color(
int nRed,
int nGreen,
int nBlue,
int nAlpha) noexcept
140 :
color(dec_to_float(nRed), dec_to_float(nGreen), dec_to_float(nBlue), dec_to_float(nAlpha))
144 constexpr color::color(
u64 nHexValue) noexcept
146 dec_to_float(nHexValue >> 24 & 0xFF),
147 dec_to_float(nHexValue >> 16 & 0xFF),
148 dec_to_float(nHexValue >> 8 & 0xFF),
149 dec_to_float(nHexValue >> 0 & 0xFF))
153 constexpr color::color(
const glm::ivec3& vec3) noexcept
154 :
color(dec_to_float(vec3.x), dec_to_float(vec3.y), dec_to_float(vec3.z), 1.f)
158 constexpr color::color(
const glm::ivec4& vec4) noexcept
159 :
color(dec_to_float(vec4.x), dec_to_float(vec4.y), dec_to_float(vec4.z), dec_to_float(vec4.w))
185 return m_Color[
static_cast<glm::length_t
>(i)];
190 return m_Color[
static_cast<glm::length_t
>(i)];
195 return float_to_dec(m_Color.x);
200 return float_to_dec(m_Color.y);
205 return float_to_dec(m_Color.z);
210 return float_to_dec(m_Color.w);
220 const unsigned int r =
static_cast<unsigned int>(float_to_dec(m_Color.x));
221 const unsigned int g =
static_cast<unsigned int>(float_to_dec(m_Color.y));
222 const unsigned int b =
static_cast<unsigned int>(float_to_dec(m_Color.z));
224 return ((
r & 0xff) << 16) + ((
g & 0xff) << 8) + ((
b & 0xff) << 0);
229 const unsigned int r =
static_cast<unsigned int>(float_to_dec(m_Color.x));
230 const unsigned int g =
static_cast<unsigned int>(float_to_dec(m_Color.y));
231 const unsigned int b =
static_cast<unsigned int>(float_to_dec(m_Color.z));
232 const unsigned int a =
static_cast<unsigned int>(float_to_dec(m_Color.w));
234 return ((
r & 0xff) << 24) + ((
g & 0xff) << 16) + ((
b & 0xff) << 8) + (
a & 0xff);
239 const unsigned int r =
static_cast<unsigned int>(float_to_dec(m_Color.x));
240 const unsigned int g =
static_cast<unsigned int>(float_to_dec(m_Color.y));
241 const unsigned int b =
static_cast<unsigned int>(float_to_dec(m_Color.z));
242 const unsigned int a =
static_cast<unsigned int>(float_to_dec(m_Color.w));
244 return ((
a & 0xff) << 24) + ((
r & 0xff) << 16) + ((
g & 0xff) << 8) + (
b & 0xff);
247 constexpr
bool color::operator==(
const color& other)
const noexcept
249 return m_Color == other.m_Color;
252 constexpr color::operator glm::vec3() const noexcept
257 constexpr color::operator glm::vec4() const noexcept
264 assign_component_checked(m_Color.x, m_Color.x + fDeltaValue);
269 assign_component_checked(m_Color.y, m_Color.y + fDeltaValue);
274 assign_component_checked(m_Color.z, m_Color.z + fDeltaValue);
279 assign_component_checked(m_Color.w, m_Color.w + fDeltaValue);
284 assign_component_checked(m_Color.x, m_Color.x + dec_to_float(nDeltaValue));
289 assign_component_checked(m_Color.y, m_Color.y + dec_to_float(nDeltaValue));
294 assign_component_checked(m_Color.z, m_Color.z + dec_to_float(nDeltaValue));
299 assign_component_checked(m_Color.w, m_Color.w + dec_to_float(nDeltaValue));
304 assign_component_checked(m_Color.x, fValue);
309 assign_component_checked(m_Color.y, fValue);
314 assign_component_checked(m_Color.z, fValue);
319 assign_component_checked(m_Color.w, fValue);
324 assign_component_checked(m_Color.x, dec_to_float(nValue));
329 assign_component_checked(m_Color.y, dec_to_float(nValue));
334 assign_component_checked(m_Color.z, dec_to_float(nValue));
339 assign_component_checked(m_Color.w, dec_to_float(nValue));
349 m_Color.x *= (100.f + fPercent) / 100.f;
350 m_Color.y *= (100.f + fPercent) / 100.f;
351 m_Color.z *= (100.f + fPercent) / 100.f;
373 std::optional<color> optColor;
375 const bool bStartsWith0x =
376 svColorName.starts_with(QXT(
"0x")) && (svColorName.size() == 8 || svColorName.size() == 10);
378 if (bStartsWith0x || svColorName.starts_with(QXT(
"#")) && svColorName.size() == 7)
382 const size_t nOffset = bStartsWith0x ? 2 : 1;
383 string sColorName = string_view(svColorName.data() + nOffset, svColorName.size() - nOffset);
385 auto ReadHex = [](
string& s) -> std::optional<color>
388 if (
const auto optInt = s.template to<u64>(QXT(
"%llx")))
389 return color(*optInt);
394 if (sColorName.
length() == 6)
396 sColorName += QXT(
"FF");
397 optColor = ReadHex(sColorName);
399 else if (sColorName.
length() == 8)
401 optColor = ReadHex(sColorName);
411 static_cast<u8>(nHash >> 0 & 0xFF),
412 static_cast<u8>(nHash >> 8 & 0xFF),
413 static_cast<u8>(nHash >> 16 & 0xFF));
418 return color(0, 0, 0, 0);
423 return glm::vec4::length();
426 constexpr
float color::clamp_value(
float fValue) noexcept
428 return std::clamp(fValue, 0.f, 1.f);
431 constexpr
float color::dec_to_float(
int nValue) noexcept
433 return static_cast<float>(nValue) / 255.f;
436 constexpr
int color::float_to_dec(
float fValue) noexcept
445 return static_cast<int>(fValue * 255.f);
448 constexpr
void color::assign_checked(
const glm::vec4& other) noexcept
450 assign_component_checked(m_Color.x, other.x);
451 assign_component_checked(m_Color.y, other.y);
452 assign_component_checked(m_Color.z, other.z);
453 assign_component_checked(m_Color.w, other.w);
456 constexpr
void color::assign_component_checked(
float& pComponent,
float fValue) noexcept
458 pComponent = clamp_value(fValue);
463 template<
class char_t>
464 struct QX_FMT_NS::formatter<qx::color, char_t>
466 template<
class format_parse_context_t>
467 constexpr
auto parse(format_parse_context_t& ctx)
469 auto it = ctx.begin();
475 optColorNameType = qx::color_name_type::css_snake;
480 optColorNameType = qx::color_name_type::css_pascal;
485 optColorNameType = qx::color_name_type::hex_lower;
490 optColorNameType = qx::color_name_type::hex_upper;
495 optColorNameType = qx::color_name_type::rgb;
509 throw QX_FMT_NS::format_error(
"unknown spec");
514 template<
class format_context_t>
515 auto format(
const qx::color& color, format_context_t& ctx)
const -> decltype(ctx.out())
517 const qx::color_name_type eColorNameType =
518 optColorNameType ? *optColorNameType : qx::color_name_type::hex_upper;
520 std::optional<qx::basic_string_view<char_t>> optResult =
525 return QX_FMT_NS::format_to(ctx.out(),
QX_STR_PREFIX(char_t,
"{}"), *optResult);
529 if (eColorNameType == qx::color_name_type::rgb)
531 auto it = QX_FMT_NS::format_to(
543 else if (eColorNameType == qx::color_name_type::hex_lower)
545 auto it = QX_FMT_NS::format_to(
560 auto it = QX_FMT_NS::format_to(
567 if (bAddAlpha || !optColorNameType)
575 std::optional<qx::color_name_type> optColorNameType;
576 bool bAddAlpha =
false;
size_type length() const noexcept
Get string length.
constexpr float g() const noexcept
Get green component.
constexpr void update_r_dec(int nDeltaValue) noexcept
Add value to red component.
constexpr void update_a(float fDeltaValue) noexcept
Add value to alpha component.
constexpr int r_dec() const noexcept
Get red component as decimal.
static std::optional< color > from_string(string_view svColorName) noexcept
Try to create color from string.
constexpr void update_g(float fDeltaValue) noexcept
Add value to green component.
constexpr void update_b(float fDeltaValue) noexcept
Add value to blue component.
constexpr void darken(float fPercent) noexcept
Make color darker.
constexpr int g_dec() const noexcept
Get green component as decimal.
constexpr float a() const noexcept
Get alpha component.
constexpr const float * data() const noexcept
Get pointer to the first component.
constexpr float b() const noexcept
Get blue component.
constexpr float r() const noexcept
Get red component.
constexpr void set_g(float fValue) noexcept
Set new value of green component.
constexpr float & operator[](size_t i) noexcept
Get color component.
constexpr void set_b(float fValue) noexcept
Set new value of blue component.
constexpr int b_dec() const noexcept
Get blue component as decimal.
static constexpr color from_hash(size_t nHash) noexcept
Generate a color unique for a hash value.
static constexpr color empty() noexcept
Get empty color (0, 0, 0, 0)
constexpr void update_g_dec(int nDeltaValue) noexcept
Add value to green component.
constexpr void set_r(float fValue) noexcept
Set new value of red component.
constexpr unsigned int hex_rgba() const noexcept
Get color as hex.
constexpr unsigned int hex_rgb() const noexcept
Get color as hex.
constexpr void update_r(float fDeltaValue) noexcept
Add value to red component.
constexpr int a_dec() const noexcept
Get alpha component as decimal.
constexpr void set_g_dec(int nValue) noexcept
Set new value of green component.
static constexpr size_t size() noexcept
Get number of float components.
constexpr void brighten(float fPercent) noexcept
Make color brighter.
constexpr unsigned int hex_argb() const noexcept
Get color as hex.
constexpr void update_b_dec(int nDeltaValue) noexcept
Add value to blue component.
constexpr void set_r_dec(int nValue) noexcept
Set new value of red component.
constexpr void set_b_dec(int nValue) noexcept
Set new value of blue component.
constexpr void update_a_dec(int nDeltaValue) noexcept
Add value to alpha component.
constexpr void set_a(float fValue) noexcept
Set new value of alpha component.
constexpr void set_a_dec(int nValue) noexcept
Set new value of alpha component.
Helper class for string -> color conversion.
std::optional< color > get(const basic_string< char_t > &sName) const noexcept
Try to get ac olor from a color name.
void add(basic_string< char_t > sName, color_name_type eColorNameType, color color) noexcept
Add new color to the mapping.
Inherit the necessary singleton class from this.
#define _QX_COLORS(macro)
#define QX_CHAR_PREFIX(value_t, ch)
Chose witch of prefixes add to char : L or none.
#define QX_STR_PREFIX(value_t, str)
Chose witch of prefixes add to string : L or none.
std::uint8_t u8
0 .. 65 535