Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix #1258: Add mixed hex and RGB(A) parsing to XMLColorToInt #1261

Merged
merged 6 commits into from Apr 1, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
26 changes: 9 additions & 17 deletions Server/mods/deathmatch/logic/CVehicle.cpp
Expand Up @@ -304,28 +304,20 @@ bool CVehicle::ReadSpecialData(const int iLine)
char szTemp[256];
if (GetCustomDataString("color", szTemp, 256, true))
{
uchar ucValues[12] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
char* sz1 = strtok(szTemp, ", ");
if (sz1)
ucValues[0] = atoi(sz1);
std::vector<SColorRGBA> vecColors;
unsigned char ucCount;

int i;
for (i = 1; i < 12; i++)
if (ColorStringToRGB(szTemp, SColorRGBA(0, 0, 0, 0), vecColors, ucCount))
{
char* szn = strtok(NULL, ", ");
if (!szn)
break;
ucValues[i] = atoi(szn);
}

if (i == 3 || i == 6 || i == 9 || i == 12)
{
m_Color.SetRGBColors(SColorRGBA(ucValues[0], ucValues[1], ucValues[2], 0), SColorRGBA(ucValues[3], ucValues[4], ucValues[5], 0),
SColorRGBA(ucValues[6], ucValues[7], ucValues[8], 0), SColorRGBA(ucValues[9], ucValues[10], ucValues[11], 0));
if (ucCount % 3 == 0)
m_Color.SetRGBColors(vecColors[0], vecColors[1], vecColors[2], vecColors[3]);
else
m_Color.SetPaletteColors(vecColors[0].R, vecColors[0].G, vecColors[0].B, vecColors[1].R);
}
else
{
m_Color.SetPaletteColors(ucValues[0], ucValues[1], ucValues[2], ucValues[3]);
CLogger::ErrorPrintf("Bad 'color' value specified in <vehicle> (line %u)\n", iLine);
return false;
}
}

Expand Down
120 changes: 111 additions & 9 deletions Server/mods/deathmatch/logic/Utils.cpp
Expand Up @@ -535,18 +535,120 @@ bool XMLColorToInt(const char* szColor, unsigned long& ulColor)

bool XMLColorToInt(const char* szColor, unsigned char& ucRed, unsigned char& ucGreen, unsigned char& ucBlue, unsigned char& ucAlpha)
{
// Convert it to an integer first
unsigned long ulColor;
if (!XMLColorToInt(szColor, ulColor))
{
// If we're empty, let's just stop right away
if (!szColor || strlen(szColor) == 0)
return false;

std::vector<SColorRGBA> vecColors;
unsigned char ucCount;

if (ColorStringToRGBA(szColor, SColorRGBA(ucRed, ucGreen, ucBlue, ucAlpha), vecColors, ucCount))
{
ucRed = vecColors[0].R;
ucGreen = vecColors[0].G;
ucBlue = vecColors[0].B;
ucAlpha = vecColors[0].A;

return true;
}

return false;
}

bool ColorStringToRGBA(const char* szColor, SColorRGBA defaultColor, std::vector<SColorRGBA>& vecColors, unsigned char& ucCount, bool bIgnoreAlpha)
{
std::stringstream ss(szColor);
SColorRGBA color = defaultColor;
bool bPreviousWasHex = false;
unsigned int uiRGBAIndex = 0;
unsigned long ulColor;
unsigned char ucValue;
unsigned char ucLength = bIgnoreAlpha ? 3 : 4;

while (ss.good())
{
// Ambiguous value before a comma
SString strValue;
getline(ss, strValue, ',');

// Remove spaces
ReplaceOccurrencesInString(strValue, " ", "");

// Is the value looking like a hexadecimal?
if (strValue[0] == '#')
patrikjuvonen marked this conversation as resolved.
Show resolved Hide resolved
{
// Try converting it to an integer
if (XMLColorToInt(strValue.c_str(), ulColor))
{
// If a previous RGBA wasn't finished, let's finish it now
if (!bPreviousWasHex && uiRGBAIndex != 0)
{
vecColors.push_back(color);
ucCount += ucLength - uiRGBAIndex;
color = defaultColor;
}

color.R = static_cast<unsigned char>(ulColor);
color.G = static_cast<unsigned char>(ulColor >> 8);
color.B = static_cast<unsigned char>(ulColor >> 16);

if (!bIgnoreAlpha)
color.A = static_cast<unsigned char>(ulColor >> 24);

bPreviousWasHex = true;
ucCount += ucLength;
}
else
return false;
}
// It looks like we have an empty value, let's skip the value but treat it as RGB
else if (strValue.empty())
{
if (bPreviousWasHex || uiRGBAIndex % ucLength == 0)
{
bPreviousWasHex = false;
uiRGBAIndex = 0;
}

uiRGBAIndex++;
ucCount++;

if (uiRGBAIndex % ucLength != 0 && ss.good())
continue;
}
// It looks like a plain number so let's treat it as a RGBA value
else if (strValue.find_first_not_of("0123456789") == std::string::npos)
{
ucValue = atoi(strValue.c_str());

if (bPreviousWasHex || uiRGBAIndex % ucLength == 0)
{
color.R = ucValue;
bPreviousWasHex = false;
uiRGBAIndex = 0;
}
else if (uiRGBAIndex % ucLength == 1)
color.G = ucValue;
else if (uiRGBAIndex % ucLength == 2)
color.B = ucValue;
else if (uiRGBAIndex % ucLength == 3)
color.A = ucValue;

uiRGBAIndex++;
ucCount++;

if (uiRGBAIndex % ucLength != 0 && ss.good())
continue;
}
else
return false;

// We have a color, so let's push it
vecColors.push_back(color);
color = defaultColor;
uiRGBAIndex = 0;
}

// Convert it to red, green, blue and alpha
ucRed = static_cast<unsigned char>(ulColor);
ucGreen = static_cast<unsigned char>(ulColor >> 8);
ucBlue = static_cast<unsigned char>(ulColor >> 16);
ucAlpha = static_cast<unsigned char>(ulColor >> 24);
return true;
}

Expand Down
5 changes: 5 additions & 0 deletions Server/mods/deathmatch/logic/Utils.h
Expand Up @@ -57,6 +57,11 @@ bool IsValidOrganizationPath(const char* szPath);
unsigned int HexToInt(const char* szHex);
bool XMLColorToInt(const char* szColor, unsigned long& ulColor);
bool XMLColorToInt(const char* szColor, unsigned char& ucRed, unsigned char& ucGreen, unsigned char& ucBlue, unsigned char& ucAlpha);
bool ColorStringToRGBA(const char* szColor, SColorRGBA defaultColor, std::vector<SColorRGBA>& vecColors, unsigned char& ucCount, bool bIgnoreAlpha = false);
inline bool ColorStringToRGB(const char* szColor, SColorRGBA defaultColor, std::vector<SColorRGBA>& vecColors, unsigned char& ucCount)
{
return ColorStringToRGBA(szColor, defaultColor, vecColors, ucCount, true);
}

inline float WrapAround(float fValue, float fHigh)
{
Expand Down