Add color_parse function to parse strings as colors

Parses RGB, RGBA, RRGGBB and RRGGBBAA hex color formats into any `color4_base`.

Reuse code from color parsing in console.
This commit is contained in:
Robert Müller 2023-06-20 23:07:44 +02:00
parent f30682be04
commit 2db569374d
4 changed files with 55 additions and 38 deletions

View file

@ -1864,6 +1864,7 @@ add_custom_command(OUTPUT "src/game/generated/wordlist.h"
set_src(BASE GLOB_RECURSE src/base
bezier.cpp
bezier.h
color.cpp
color.h
detect.h
dynamic.h

48
src/base/color.cpp Normal file
View file

@ -0,0 +1,48 @@
#include "color.h"
#include "system.h"
template<typename T>
std::optional<T> color_parse(const char *pStr)
{
if(!str_isallnum_hex(pStr))
return {};
const unsigned Num = str_toulong_base(pStr, 16);
T Color;
switch(str_length(pStr))
{
case 3:
Color.x = (((Num >> 8) & 0x0F) + ((Num >> 4) & 0xF0)) / 255.0f;
Color.y = (((Num >> 4) & 0x0F) + ((Num >> 0) & 0xF0)) / 255.0f;
Color.z = (((Num >> 0) & 0x0F) + ((Num << 4) & 0xF0)) / 255.0f;
Color.a = 1.0f;
return Color;
case 4:
Color.x = (((Num >> 12) & 0x0F) + ((Num >> 8) & 0xF0)) / 255.0f;
Color.y = (((Num >> 8) & 0x0F) + ((Num >> 4) & 0xF0)) / 255.0f;
Color.z = (((Num >> 4) & 0x0F) + ((Num >> 0) & 0xF0)) / 255.0f;
Color.a = (((Num >> 0) & 0x0F) + ((Num << 4) & 0xF0)) / 255.0f;
return Color;
case 6:
Color.x = ((Num >> 16) & 0xFF) / 255.0f;
Color.y = ((Num >> 8) & 0xFF) / 255.0f;
Color.z = ((Num >> 0) & 0xFF) / 255.0f;
Color.a = 1.0f;
return Color;
case 8:
Color.x = ((Num >> 24) & 0xFF) / 255.0f;
Color.y = ((Num >> 16) & 0xFF) / 255.0f;
Color.z = ((Num >> 8) & 0xFF) / 255.0f;
Color.a = ((Num >> 0) & 0xFF) / 255.0f;
return Color;
default:
return {};
}
}
template std::optional<ColorRGBA> color_parse<ColorRGBA>(const char *);

View file

@ -5,6 +5,8 @@
#include <base/math.h>
#include <base/vmath.h>
#include <optional>
/*
Title: Color handling
*/
@ -290,4 +292,7 @@ T color_invert(const T &col)
return T(1.0f - col.x, 1.0f - col.y, 1.0f - col.z, 1.0f - col.a);
}
template<typename T>
std::optional<T> color_parse(const char *pStr);
#endif

View file

@ -55,44 +55,7 @@ ColorHSLA CConsole::CResult::GetColor(unsigned Index, bool Light) const
}
else if(*pStr == '$') // Hex RGB/RGBA
{
ColorRGBA Rgba = ColorRGBA(0, 0, 0, 1);
const int Len = str_length(pStr);
if(Len == 4)
{
const unsigned Num = str_toulong_base(pStr + 1, 16);
Rgba.r = (((Num >> 8) & 0x0F) + ((Num >> 4) & 0xF0)) / 255.0f;
Rgba.g = (((Num >> 4) & 0x0F) + ((Num >> 0) & 0xF0)) / 255.0f;
Rgba.b = (((Num >> 0) & 0x0F) + ((Num << 4) & 0xF0)) / 255.0f;
}
else if(Len == 5)
{
const unsigned Num = str_toulong_base(pStr + 1, 16);
Rgba.r = (((Num >> 12) & 0x0F) + ((Num >> 8) & 0xF0)) / 255.0f;
Rgba.g = (((Num >> 8) & 0x0F) + ((Num >> 4) & 0xF0)) / 255.0f;
Rgba.b = (((Num >> 4) & 0x0F) + ((Num >> 0) & 0xF0)) / 255.0f;
Rgba.a = (((Num >> 0) & 0x0F) + ((Num << 4) & 0xF0)) / 255.0f;
}
else if(Len == 7)
{
const unsigned Num = str_toulong_base(pStr + 1, 16);
Rgba.r = ((Num >> 16) & 0xFF) / 255.0f;
Rgba.g = ((Num >> 8) & 0xFF) / 255.0f;
Rgba.b = ((Num >> 0) & 0xFF) / 255.0f;
}
else if(Len == 9)
{
const unsigned Num = str_toulong_base(pStr + 1, 16);
Rgba.r = ((Num >> 24) & 0xFF) / 255.0f;
Rgba.g = ((Num >> 16) & 0xFF) / 255.0f;
Rgba.b = ((Num >> 8) & 0xFF) / 255.0f;
Rgba.a = ((Num >> 0) & 0xFF) / 255.0f;
}
else
{
return ColorHSLA(0, 0, 0);
}
return color_cast<ColorHSLA>(Rgba);
return color_cast<ColorHSLA>(color_parse<ColorRGBA>(pStr + 1).value_or(ColorRGBA(0.0f, 0.0f, 0.0f, 1.0f)));
}
else if(!str_comp_nocase(pStr, "red"))
return ColorHSLA(0.0f / 6.0f, 1, .5f);