From e425615770d48fc8b204df5172dbd509b496a3fc Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 11 Apr 2020 13:49:36 +0200 Subject: [PATCH] - moved the V_GetColor family of functions to the global palette utilities. --- src/common/utility/palette.cpp | 227 +++++++++++++++++++++++++++++++++ src/common/utility/palutil.h | 13 ++ src/console/c_cvars.cpp | 8 +- src/rendering/v_video.cpp | 225 -------------------------------- src/rendering/v_video.h | 10 -- 5 files changed, 244 insertions(+), 239 deletions(-) diff --git a/src/common/utility/palette.cpp b/src/common/utility/palette.cpp index fbf9c6844..5518b7235 100644 --- a/src/common/utility/palette.cpp +++ b/src/common/utility/palette.cpp @@ -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); +} + diff --git a/src/common/utility/palutil.h b/src/common/utility/palutil.h index 968c0c5a8..089f53526 100644 --- a/src/common/utility/palutil.h +++ b/src/common/utility/palutil.h @@ -3,6 +3,9 @@ #include #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); diff --git a/src/console/c_cvars.cpp b/src/console/c_cvars.cpp index 4cadbb367..a8f5ab2b5 100644 --- a/src/console/c_cvars.cpp +++ b/src/console/c_cvars.cpp @@ -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); } diff --git a/src/rendering/v_video.cpp b/src/rendering/v_video.cpp index d4607dba5..e22cdc128 100644 --- a/src/rendering/v_video.cpp +++ b/src/rendering/v_video.cpp @@ -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); diff --git a/src/rendering/v_video.h b/src/rendering/v_video.h index 3ced85d51..f72a65c7a 100644 --- a/src/rendering/v_video.h +++ b/src/rendering/v_video.h @@ -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; }