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));
62 if (eColorNameType == color_name_type::css_snake)
63 m_ColorToCssSnake[
color] = sName;
64 else if (eColorNameType == color_name_type::css_pascal)
65 m_ColorToCssPascal[
color] = sName;
67 m_StringToColor[sName] = std::move(
color);
77 if (
const auto it = m_StringToColor.find(sName); it != m_StringToColor.end())
89 std::optional<basic_string_view<char_t>>
get(
const color&
color, color_name_type eColorNameType)
const noexcept
91 if (eColorNameType == color_name_type::css_snake)
93 if (
const auto it = m_ColorToCssSnake.find(
color); it != m_ColorToCssSnake.end())
96 else if (eColorNameType == color_name_type::css_pascal)
98 if (
const auto it = m_ColorToCssPascal.find(
color); it != m_ColorToCssPascal.end())
106 std::unordered_map<basic_string<char_t>,
color> m_StringToColor;
107 std::unordered_map<color, basic_string<char_t>> m_ColorToCssSnake;
108 std::unordered_map<color, basic_string<char_t>> m_ColorToCssPascal;
113 constexpr color::color(
float fRed,
float fGreen,
float fBlue,
float fAlpha) noexcept
115 assign_checked({ fRed, fGreen, fBlue, fAlpha });
118 constexpr color::color(
int nRed,
int nGreen,
int nBlue,
int nAlpha) noexcept
119 :
color(dec_to_float(nRed), dec_to_float(nGreen), dec_to_float(nBlue), dec_to_float(nAlpha))
123 constexpr color::color(
u64 nHexValue) noexcept
125 dec_to_float(nHexValue >> 24 & 0xFF),
126 dec_to_float(nHexValue >> 16 & 0xFF),
127 dec_to_float(nHexValue >> 8 & 0xFF),
128 dec_to_float(nHexValue >> 0 & 0xFF))
132 constexpr color::color(
const glm::ivec3& vec3) noexcept
133 :
color(dec_to_float(vec3.x), dec_to_float(vec3.y), dec_to_float(vec3.z), 1.f)
137 constexpr color::color(
const glm::ivec4& vec4) noexcept
138 :
color(dec_to_float(vec4.x), dec_to_float(vec4.y), dec_to_float(vec4.z), dec_to_float(vec4.w))
164 return m_Color[
static_cast<glm::length_t
>(i)];
169 return m_Color[
static_cast<glm::length_t
>(i)];
174 return float_to_dec(m_Color.x);
179 return float_to_dec(m_Color.y);
184 return float_to_dec(m_Color.z);
189 return float_to_dec(m_Color.w);
199 const unsigned int r =
static_cast<unsigned int>(float_to_dec(m_Color.x));
200 const unsigned int g =
static_cast<unsigned int>(float_to_dec(m_Color.y));
201 const unsigned int b =
static_cast<unsigned int>(float_to_dec(m_Color.z));
203 return ((
r & 0xff) << 16) + ((
g & 0xff) << 8) + ((
b & 0xff) << 0);
208 const unsigned int r =
static_cast<unsigned int>(float_to_dec(m_Color.x));
209 const unsigned int g =
static_cast<unsigned int>(float_to_dec(m_Color.y));
210 const unsigned int b =
static_cast<unsigned int>(float_to_dec(m_Color.z));
211 const unsigned int a =
static_cast<unsigned int>(float_to_dec(m_Color.w));
213 return ((
r & 0xff) << 24) + ((
g & 0xff) << 16) + ((
b & 0xff) << 8) + (
a & 0xff);
218 const unsigned int r =
static_cast<unsigned int>(float_to_dec(m_Color.x));
219 const unsigned int g =
static_cast<unsigned int>(float_to_dec(m_Color.y));
220 const unsigned int b =
static_cast<unsigned int>(float_to_dec(m_Color.z));
221 const unsigned int a =
static_cast<unsigned int>(float_to_dec(m_Color.w));
223 return ((
a & 0xff) << 24) + ((
r & 0xff) << 16) + ((
g & 0xff) << 8) + (
b & 0xff);
226 constexpr
bool color::operator==(
const color& other)
const noexcept
228 return m_Color == other.m_Color;
231 constexpr color::operator glm::vec3() const noexcept
236 constexpr color::operator glm::vec4() const noexcept
243 assign_component_checked(m_Color.x, m_Color.x + fDeltaValue);
248 assign_component_checked(m_Color.y, m_Color.y + fDeltaValue);
253 assign_component_checked(m_Color.z, m_Color.z + fDeltaValue);
258 assign_component_checked(m_Color.w, m_Color.w + fDeltaValue);
263 assign_component_checked(m_Color.x, m_Color.x + dec_to_float(nDeltaValue));
268 assign_component_checked(m_Color.y, m_Color.y + dec_to_float(nDeltaValue));
273 assign_component_checked(m_Color.z, m_Color.z + dec_to_float(nDeltaValue));
278 assign_component_checked(m_Color.w, m_Color.w + dec_to_float(nDeltaValue));
283 assign_component_checked(m_Color.x, fValue);
288 assign_component_checked(m_Color.y, fValue);
293 assign_component_checked(m_Color.z, fValue);
298 assign_component_checked(m_Color.w, fValue);
303 assign_component_checked(m_Color.x, dec_to_float(nValue));
308 assign_component_checked(m_Color.y, dec_to_float(nValue));
313 assign_component_checked(m_Color.z, dec_to_float(nValue));
318 assign_component_checked(m_Color.w, dec_to_float(nValue));
328 m_Color.x *= (100.f + fPercent) / 100.f;
329 m_Color.y *= (100.f + fPercent) / 100.f;
330 m_Color.z *= (100.f + fPercent) / 100.f;
352 std::optional<color> optColor;
354 const bool bStartsWith0x =
355 svColorName.starts_with(QX_TEXT(
"0x")) && (svColorName.size() == 8 || svColorName.size() == 10);
357 if (bStartsWith0x || svColorName.starts_with(QX_TEXT(
"#")) && svColorName.size() == 7)
361 const size_t nOffset = bStartsWith0x ? 2 : 1;
362 string sColorName = string_view(svColorName.data() + nOffset, svColorName.size() - nOffset);
364 auto ReadHex = [](
string& s) -> std::optional<color>
367 if (
const auto optInt = s.template to<u64>(QX_TEXT(
"%llx")))
368 return color(*optInt);
373 if (sColorName.
length() == 6)
375 sColorName += QX_TEXT(
"FF");
376 optColor = ReadHex(sColorName);
378 else if (sColorName.
length() == 8)
380 optColor = ReadHex(sColorName);
389 return color(0, 0, 0, 0);
397 constexpr
float color::clamp_value(
float fValue) noexcept
399 return std::clamp(fValue, 0.f, 1.f);
402 constexpr
float color::dec_to_float(
int nValue) noexcept
404 return static_cast<float>(nValue) / 255.f;
407 constexpr
int color::float_to_dec(
float fValue) noexcept
409 return static_cast<int>(fValue * 255.f);
412 constexpr
void color::assign_checked(
const glm::vec4& other) noexcept
414 assign_component_checked(m_Color.x, other.x);
415 assign_component_checked(m_Color.y, other.y);
416 assign_component_checked(m_Color.z, other.z);
417 assign_component_checked(m_Color.w, other.w);
420 constexpr
void color::assign_component_checked(
float& pComponent,
float fValue) noexcept
422 pComponent = clamp_value(fValue);
427 template<
class char_t>
428 struct std::formatter<qx::color, char_t>
430 template<
class format_parse_context_t>
431 constexpr
auto parse(format_parse_context_t& ctx)
433 auto it = ctx.begin();
439 optColorNameType = qx::color_name_type::css_snake;
444 optColorNameType = qx::color_name_type::css_pascal;
449 optColorNameType = qx::color_name_type::hex_lower;
454 optColorNameType = qx::color_name_type::hex_upper;
459 optColorNameType = qx::color_name_type::rgb;
473 throw std::format_error(
"unknown spec");
478 template<
class format_context_t>
479 auto format(
const qx::color& color, format_context_t& ctx)
const
481 const qx::color_name_type eColorNameType =
482 optColorNameType ? *optColorNameType : qx::color_name_type::hex_upper;
484 std::optional<qx::basic_string_view<char_t>> optResult =
489 return std::format_to(ctx.out(),
QX_STR_PREFIX(char_t,
"{}"), *optResult);
493 if (eColorNameType == qx::color_name_type::rgb)
495 auto it = std::format_to(
507 else if (eColorNameType == qx::color_name_type::hex_lower)
509 auto it = std::format_to(
524 auto it = std::format_to(
531 if (bAddAlpha || !optColorNameType)
539 std::optional<qx::color_name_type> optColorNameType;
540 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 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.
void add(basic_string< char_t > sName, color_name_type eColorNameType, color color) noexcept
Add new color to the mapping.
std::optional< basic_string_view< char_t > > get(const color &color, color_name_type eColorNameType) const noexcept
Try to a color name get from a color.
std::optional< color > get(const basic_string< char_t > &sName) const noexcept
Try to get ac olor from a color name.
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.