- moved the V_GetColor family of functions to the global palette utilities.

This commit is contained in:
Christoph Oelckers 2020-04-11 13:49:36 +02:00
parent 1479e3a1c3
commit e425615770
5 changed files with 244 additions and 239 deletions

View file

@ -37,6 +37,8 @@
#include "palentry.h"
#include "sc_man.h"
#include "files.h"
#include "filesystem.h"
#include "printf.h"
/****************************/
/* Palette management stuff */
@ -467,3 +469,228 @@ void MakeGoodRemap(uint32_t* BaseColors, uint8_t* Remap)
// 256 entries are different. :-)
}
//==========================================================================
//
// V_GetColorFromString
//
// Passed a string of the form "#RGB", "#RRGGBB", "R G B", or "RR GG BB",
// returns a number representing that color. If palette is non-NULL, the
// index of the best match in the palette is returned, otherwise the
// RRGGBB value is returned directly.
//
//==========================================================================
int V_GetColorFromString(const uint32_t* palette, const char* cstr, FScriptPosition* sc)
{
int c[3], i, p;
char val[3];
val[2] = '\0';
// Check for HTML-style #RRGGBB or #RGB color string
if (cstr[0] == '#')
{
size_t len = strlen(cstr);
if (len == 7)
{
// Extract each eight-bit component into c[].
for (i = 0; i < 3; ++i)
{
val[0] = cstr[1 + i * 2];
val[1] = cstr[2 + i * 2];
c[i] = ParseHex(val, sc);
}
}
else if (len == 4)
{
// Extract each four-bit component into c[], expanding to eight bits.
for (i = 0; i < 3; ++i)
{
val[1] = val[0] = cstr[1 + i];
c[i] = ParseHex(val, sc);
}
}
else
{
// Bad HTML-style; pretend it's black.
c[2] = c[1] = c[0] = 0;
}
}
else
{
if (strlen(cstr) == 6)
{
char* p;
int color = strtol(cstr, &p, 16);
if (*p == 0)
{
// RRGGBB string
c[0] = (color & 0xff0000) >> 16;
c[1] = (color & 0xff00) >> 8;
c[2] = (color & 0xff);
}
else goto normal;
}
else
{
normal:
// Treat it as a space-delimited hexadecimal string
for (i = 0; i < 3; ++i)
{
// Skip leading whitespace
while (*cstr <= ' ' && *cstr != '\0')
{
cstr++;
}
// Extract a component and convert it to eight-bit
for (p = 0; *cstr > ' '; ++p, ++cstr)
{
if (p < 2)
{
val[p] = *cstr;
}
}
if (p == 0)
{
c[i] = 0;
}
else
{
if (p == 1)
{
val[1] = val[0];
}
c[i] = ParseHex(val, sc);
}
}
}
}
if (palette)
return BestColor(palette, c[0], c[1], c[2]);
else
return MAKERGB(c[0], c[1], c[2]);
}
//==========================================================================
//
// V_GetColorStringByName
//
// Searches for the given color name in x11r6rgb.txt and returns an
// HTML-ish "#RRGGBB" string for it if found or the empty string if not.
//
//==========================================================================
FString V_GetColorStringByName(const char* name, FScriptPosition* sc)
{
FileData rgbNames;
char* rgbEnd;
char* rgb, * endp;
int rgblump;
int c[3], step;
size_t namelen;
if (fileSystem.GetNumEntries() == 0) return FString();
rgblump = fileSystem.CheckNumForName("X11R6RGB");
if (rgblump == -1)
{
if (!sc) Printf("X11R6RGB lump not found\n");
else sc->Message(MSG_WARNING, "X11R6RGB lump not found");
return FString();
}
rgbNames = fileSystem.ReadFile(rgblump);
rgb = (char*)rgbNames.GetMem();
rgbEnd = rgb + fileSystem.FileLength(rgblump);
step = 0;
namelen = strlen(name);
while (rgb < rgbEnd)
{
// Skip white space
if (*rgb <= ' ')
{
do
{
rgb++;
} while (rgb < rgbEnd && *rgb <= ' ');
}
else if (step == 0 && *rgb == '!')
{ // skip comment lines
do
{
rgb++;
} while (rgb < rgbEnd && *rgb != '\n');
}
else if (step < 3)
{ // collect RGB values
c[step++] = strtoul(rgb, &endp, 10);
if (endp == rgb)
{
break;
}
rgb = endp;
}
else
{ // Check color name
endp = rgb;
// Find the end of the line
while (endp < rgbEnd && *endp != '\n')
endp++;
// Back up over any whitespace
while (endp > rgb && *endp <= ' ')
endp--;
if (endp == rgb)
{
break;
}
size_t checklen = ++endp - rgb;
if (checklen == namelen && strnicmp(rgb, name, checklen) == 0)
{
FString descr;
descr.Format("#%02x%02x%02x", c[0], c[1], c[2]);
return descr;
}
rgb = endp;
step = 0;
}
}
if (rgb < rgbEnd)
{
if (!sc) Printf("X11R6RGB lump is corrupt\n");
else sc->Message(MSG_WARNING, "X11R6RGB lump is corrupt");
}
return FString();
}
//==========================================================================
//
// V_GetColor
//
// Works like V_GetColorFromString(), but also understands X11 color names.
//
//==========================================================================
int V_GetColor(const uint32_t* palette, const char* str, FScriptPosition* sc)
{
FString string = V_GetColorStringByName(str, sc);
int res;
if (!string.IsEmpty())
{
res = V_GetColorFromString(palette, string, sc);
}
else
{
res = V_GetColorFromString(palette, str, sc);
}
return res;
}
int V_GetColor(const uint32_t* palette, FScanner& sc)
{
FScriptPosition scc = sc;
return V_GetColor(palette, sc.String, &scc);
}

View file

@ -3,6 +3,9 @@
#include <stdint.h>
#include "palentry.h"
struct FScriptPosition;
class FScanner;
int BestColor(const uint32_t* pal, int r, int g, int b, int first = 1, int num = 255);
int PTM_BestColor(const uint32_t* pal_in, int r, int g, int b, bool reverselookup, float powtable, int first = 1, int num = 255);
void DoBlending(const PalEntry* from, PalEntry* to, int count, int r, int g, int b, int a);
@ -16,3 +19,13 @@ void MakeGoodRemap(uint32_t* BaseColors, uint8_t* Remap);
void RGBtoHSV (float r, float g, float b, float *h, float *s, float *v);
void HSVtoRGB (float *r, float *g, float *b, float h, float s, float v);
// Returns the closest color to the one desired. String
// should be of the form "rr gg bb".
int V_GetColorFromString(const uint32_t* palette, const char* colorstring, FScriptPosition* sc = nullptr);
// Scans through the X11R6RGB lump for a matching color
// and returns a color string suitable for V_GetColorFromString.
FString V_GetColorStringByName(const char* name, FScriptPosition* sc = nullptr);
// Tries to get color by name, then by string
int V_GetColor(const uint32_t* palette, const char* str, FScriptPosition* sc = nullptr);
int V_GetColor(const uint32_t* palette, FScanner& sc);

View file

@ -42,8 +42,7 @@
#include "c_cvars.h"
#include "engineerrors.h"
#include "printf.h"
#include "v_video.h" // for color lookup - move to utility code!!!
#include "palutil.h"
//#include "version.h"
@ -820,12 +819,13 @@ int FColorCVar::ToInt2 (UCVarValue value, ECVarType type)
if (type == CVAR_String)
{
FString string;
FString string = V_GetColorStringByName(value.String);
// Only allow named colors after the screen exists (i.e. after
// we've got some lumps loaded, so X11R6RGB can be read). Since
// the only time this might be called before that is when loading
// zdoom.ini, this shouldn't be a problem.
if (screen && !(string = V_GetColorStringByName (value.String)).IsEmpty() )
if (string.IsNotEmpty())
{
ret = V_GetColorFromString (NULL, string);
}

View file

@ -266,231 +266,6 @@ void DCanvas::Resize(int width, int height, bool optimizepitch)
}
//==========================================================================
//
// V_GetColorFromString
//
// Passed a string of the form "#RGB", "#RRGGBB", "R G B", or "RR GG BB",
// returns a number representing that color. If palette is non-NULL, the
// index of the best match in the palette is returned, otherwise the
// RRGGBB value is returned directly.
//
//==========================================================================
int V_GetColorFromString (const uint32_t *palette, const char *cstr, FScriptPosition *sc)
{
int c[3], i, p;
char val[3];
val[2] = '\0';
// Check for HTML-style #RRGGBB or #RGB color string
if (cstr[0] == '#')
{
size_t len = strlen (cstr);
if (len == 7)
{
// Extract each eight-bit component into c[].
for (i = 0; i < 3; ++i)
{
val[0] = cstr[1 + i*2];
val[1] = cstr[2 + i*2];
c[i] = ParseHex (val, sc);
}
}
else if (len == 4)
{
// Extract each four-bit component into c[], expanding to eight bits.
for (i = 0; i < 3; ++i)
{
val[1] = val[0] = cstr[1 + i];
c[i] = ParseHex (val, sc);
}
}
else
{
// Bad HTML-style; pretend it's black.
c[2] = c[1] = c[0] = 0;
}
}
else
{
if (strlen(cstr) == 6)
{
char *p;
int color = strtol(cstr, &p, 16);
if (*p == 0)
{
// RRGGBB string
c[0] = (color & 0xff0000) >> 16;
c[1] = (color & 0xff00) >> 8;
c[2] = (color & 0xff);
}
else goto normal;
}
else
{
normal:
// Treat it as a space-delimited hexadecimal string
for (i = 0; i < 3; ++i)
{
// Skip leading whitespace
while (*cstr <= ' ' && *cstr != '\0')
{
cstr++;
}
// Extract a component and convert it to eight-bit
for (p = 0; *cstr > ' '; ++p, ++cstr)
{
if (p < 2)
{
val[p] = *cstr;
}
}
if (p == 0)
{
c[i] = 0;
}
else
{
if (p == 1)
{
val[1] = val[0];
}
c[i] = ParseHex (val, sc);
}
}
}
}
if (palette)
return ColorMatcher.Pick (c[0], c[1], c[2]);
else
return MAKERGB(c[0], c[1], c[2]);
}
//==========================================================================
//
// V_GetColorStringByName
//
// Searches for the given color name in x11r6rgb.txt and returns an
// HTML-ish "#RRGGBB" string for it if found or the empty string if not.
//
//==========================================================================
FString V_GetColorStringByName (const char *name, FScriptPosition *sc)
{
FileData rgbNames;
char *rgbEnd;
char *rgb, *endp;
int rgblump;
int c[3], step;
size_t namelen;
if (fileSystem.GetNumEntries()==0) return FString();
rgblump = fileSystem.CheckNumForName ("X11R6RGB");
if (rgblump == -1)
{
if (!sc) Printf ("X11R6RGB lump not found\n");
else sc->Message(MSG_WARNING, "X11R6RGB lump not found");
return FString();
}
rgbNames = fileSystem.ReadFile (rgblump);
rgb = (char *)rgbNames.GetMem();
rgbEnd = rgb + fileSystem.FileLength (rgblump);
step = 0;
namelen = strlen (name);
while (rgb < rgbEnd)
{
// Skip white space
if (*rgb <= ' ')
{
do
{
rgb++;
} while (rgb < rgbEnd && *rgb <= ' ');
}
else if (step == 0 && *rgb == '!')
{ // skip comment lines
do
{
rgb++;
} while (rgb < rgbEnd && *rgb != '\n');
}
else if (step < 3)
{ // collect RGB values
c[step++] = strtoul (rgb, &endp, 10);
if (endp == rgb)
{
break;
}
rgb = endp;
}
else
{ // Check color name
endp = rgb;
// Find the end of the line
while (endp < rgbEnd && *endp != '\n')
endp++;
// Back up over any whitespace
while (endp > rgb && *endp <= ' ')
endp--;
if (endp == rgb)
{
break;
}
size_t checklen = ++endp - rgb;
if (checklen == namelen && strnicmp (rgb, name, checklen) == 0)
{
FString descr;
descr.Format ("#%02x%02x%02x", c[0], c[1], c[2]);
return descr;
}
rgb = endp;
step = 0;
}
}
if (rgb < rgbEnd)
{
if (!sc) Printf ("X11R6RGB lump is corrupt\n");
else sc->Message(MSG_WARNING, "X11R6RGB lump is corrupt");
}
return FString();
}
//==========================================================================
//
// V_GetColor
//
// Works like V_GetColorFromString(), but also understands X11 color names.
//
//==========================================================================
int V_GetColor (const uint32_t *palette, const char *str, FScriptPosition *sc)
{
FString string = V_GetColorStringByName (str, sc);
int res;
if (!string.IsEmpty())
{
res = V_GetColorFromString (palette, string, sc);
}
else
{
res = V_GetColorFromString (palette, str, sc);
}
return res;
}
int V_GetColor(const uint32_t *palette, FScanner &sc)
{
FScriptPosition scc = sc;
return V_GetColor(palette, sc.String, &scc);
}
CCMD(clean)
{
Printf ("CleanXfac: %d\nCleanYfac: %d\n", CleanXfac, CleanYfac);

View file

@ -613,16 +613,6 @@ void V_Shutdown ();
class FScanner;
struct FScriptPosition;
// Returns the closest color to the one desired. String
// should be of the form "rr gg bb".
int V_GetColorFromString (const uint32_t *palette, const char *colorstring, FScriptPosition *sc = nullptr);
// Scans through the X11R6RGB lump for a matching color
// and returns a color string suitable for V_GetColorFromString.
FString V_GetColorStringByName (const char *name, FScriptPosition *sc = nullptr);
// Tries to get color by name, then by string
int V_GetColor (const uint32_t *palette, const char *str, FScriptPosition *sc = nullptr);
int V_GetColor(const uint32_t *palette, FScanner &sc);
inline bool IsRatioWidescreen(int ratio) { return (ratio & 3) != 0; }