- refactored the special fonts away from BuildTranslation so that this function and the entire large heap of ugly baggage it drags in can finally be deleted.

Function is gone, baggage will come next.
This commit is contained in:
Christoph Oelckers 2021-05-24 19:01:35 +02:00
parent 372d425e01
commit 9769f346ec
4 changed files with 41 additions and 144 deletions

View file

@ -750,102 +750,6 @@ int FFont::SimpleTranslation (uint32_t *colorsused, uint8_t *translation, uint8_
return j;
}
//==========================================================================
//
// FFont :: BuildTranslations
//
// Build color translations for this font. Luminosity is an array of
// brightness levels. The ActiveColors member must be set to indicate how
// large this array is. Identity is an array that remaps the colors to
// their original values; it is only used for CR_UNTRANSLATED. Ranges
// is an array of TranslationParm structs defining the ranges for every
// possible color, in order. Palette is the colors to use for the
// untranslated version of the font.
//
//==========================================================================
void FFont::BuildTranslations (const double *luminosity, const uint8_t *identity,
const void *ranges, int total_colors, const PalEntry *palette, std::function<void(FRemapTable*)> post)
{
int i, j;
const TranslationParm *parmstart = (const TranslationParm *)ranges;
FRemapTable remap(total_colors);
remap.ForFont = true;
// Create different translations for different color ranges
Translations.Clear();
for (i = 0; i < NumTextColors; i++)
{
if (i == CR_UNTRANSLATED)
{
if (identity != nullptr)
{
memcpy(remap.Remap, identity, ActiveColors);
if (palette != nullptr)
{
memcpy(remap.Palette, palette, ActiveColors * sizeof(PalEntry));
}
else
{
remap.Palette[0] = GPalette.BaseColors[identity[0]] & MAKEARGB(0, 255, 255, 255);
for (j = 1; j < ActiveColors; ++j)
{
remap.Palette[j] = GPalette.BaseColors[identity[j]] | MAKEARGB(255, 0, 0, 0);
}
}
Translations.Push(GPalette.StoreTranslation(TRANSLATION_Internal, &remap));
}
else
{
Translations.Push(Translations[0]);
}
continue;
}
assert(parmstart->RangeStart >= 0);
remap.Remap[0] = 0;
remap.Palette[0] = 0;
remap.ForFont = true;
for (j = 1; j < ActiveColors; j++)
{
int v = int(luminosity[j] * 256.0);
// Find the color range that this luminosity value lies within.
const TranslationParm *parms = parmstart - 1;
do
{
parms++;
if (parms->RangeStart <= v && parms->RangeEnd >= v)
break;
}
while (parms[1].RangeStart > parms[0].RangeEnd);
// Linearly interpolate to find out which color this luminosity level gets.
int rangev = ((v - parms->RangeStart) << 8) / (parms->RangeEnd - parms->RangeStart);
int r = ((parms->Start[0] << 8) + rangev * (parms->End[0] - parms->Start[0])) >> 8; // red
int g = ((parms->Start[1] << 8) + rangev * (parms->End[1] - parms->Start[1])) >> 8; // green
int b = ((parms->Start[2] << 8) + rangev * (parms->End[2] - parms->Start[2])) >> 8; // blue
r = clamp(r, 0, 255);
g = clamp(g, 0, 255);
b = clamp(b, 0, 255);
remap.Remap[j] = ColorMatcher.Pick(r, g, b);
remap.Palette[j] = PalEntry(255,r,g,b);
}
if (post) post(&remap);
Translations.Push(GPalette.StoreTranslation(TRANSLATION_Internal, &remap));
// Advance to the next color range.
while (parmstart[1].RangeStart > parmstart[0].RangeEnd)
{
parmstart++;
}
parmstart++;
}
}
//==========================================================================
//
// FFont :: GetColorTranslation

View file

@ -3,7 +3,6 @@
#include <stdint.h>
#include "tarray.h"
// This structure is used by BuildTranslations() to hold color information.
struct TranslationParm
{
short RangeStart; // First level for this range

View file

@ -152,61 +152,56 @@ FSpecialFont::FSpecialFont (const char *name, int first, int count, FGameTexture
void FSpecialFont::LoadTranslations()
{
int count = LastChar - FirstChar + 1;
uint32_t usedcolors[256] = {};
uint8_t identity[256];
TArray<double> Luminosity;
int TotalColors;
int i;
for (i = 0; i < count; i++)
{
if (Chars[i].OriginalPic)
{
auto pic = Chars[i].OriginalPic->GetTexture()->GetImage();
if (pic) RecordTextureColors(pic, usedcolors);
}
}
FFont::LoadTranslations();
bool needsnotrans = false;
// exclude the non-translated colors from the translation calculation
for (i = 0; i < 256; i++)
if (notranslate[i])
usedcolors[i] = false;
TotalColors = ActiveColors = SimpleTranslation (usedcolors, PatchRemap, identity, Luminosity);
// Map all untranslated colors into the table of used colors
for (i = 0; i < 256; i++)
{
for (int i = 0; i < 256; i++)
if (notranslate[i])
{
PatchRemap[i] = TotalColors;
identity[TotalColors] = i;
TotalColors++;
needsnotrans = true;
break;
}
}
for (i = 0; i < count; i++)
// If we have no non-translateable colors, we can use the base data as-is.
if (!needsnotrans)
{
if(Chars[i].TranslatedPic)
static_cast<FFontChar1 *>(Chars[i].TranslatedPic->GetTexture()->GetImage())->SetSourceRemap(PatchRemap);
return;
}
BuildTranslations(Luminosity.Data(), identity, &TranslationParms[0][0], TotalColors, nullptr, [=](FRemapTable* remap)
{
// add the untranslated colors to the Ranges tables
if (ActiveColors < TotalColors)
{
for (int j = ActiveColors; j < TotalColors; ++j)
{
remap->Remap[j] = identity[j];
remap->Palette[j] = GPalette.BaseColors[identity[j]];
remap->Palette[j].a = 0xff;
}
}
});
// we only need to add special handling if there's colors that should not be translated.
// Obviously 'notranslate' should only be used on data that uses the base palette, otherwise results are undefined!
for (auto &trans : Translations)
{
if (!IsLuminosityTranslation(trans)) continue; // this should only happen for CR_UNTRANSLATED.
ActiveColors = TotalColors;
FRemapTable remap(256);
remap.ForFont = true;
uint8_t workpal[1024];
for (int i = 0; i < 256; i++)
{
workpal[i * 4 + 0] = GPalette.BaseColors[i].b;
workpal[i * 4 + 1] = GPalette.BaseColors[i].g;
workpal[i * 4 + 2] = GPalette.BaseColors[i].r;
workpal[i * 4 + 3] = GPalette.BaseColors[i].a;
}
V_ApplyLuminosityTranslation(trans, workpal, 256);
for (int i = 0; i < 256; i++)
{
if (!notranslate[i])
{
remap.Palette[i] = PalEntry(workpal[i * 4 + 3], workpal[i * 4 + 2], workpal[i * 4 + 1], workpal[i * 4 + 0]);
remap.Remap[i] = ColorMatcher.Pick(remap.Palette[i]);
}
else
{
remap.Palette[i] = GPalette.BaseColors[i];
remap.Remap[i] = i;
}
}
trans = GPalette.StoreTranslation(TRANSLATION_Internal, &remap);
}
}
FFont *CreateSpecialFont (const char *name, int first, int count, FGameTexture **lumplist, const bool *notranslate, int lump, bool donttranslate)

View file

@ -137,8 +137,6 @@ public:
protected:
FFont (int lump);
void BuildTranslations (const double *luminosity, const uint8_t *identity,
const void *ranges, int total_colors, const PalEntry *palette, std::function<void(FRemapTable*)> post = nullptr);
void FixXMoves();
static int SimpleTranslation (uint32_t *colorsused, uint8_t *translation,
@ -192,6 +190,7 @@ EColorRange V_ParseFontColor (const uint8_t *&color_value, int normalcolor, int
FFont *V_GetFont(const char *fontname, const char *fontlumpname = nullptr);
void V_InitFontColors();
char* CleanseString(char* str);
void V_ApplyLuminosityTranslation(int translation, uint8_t* pixel, int size);
void V_LoadTranslations();
class FBitmap;