mirror of
https://github.com/ZDoom/Raze.git
synced 2024-11-15 08:51:24 +00:00
- rewrote the default translation handling to be compatible with luminosity translations.
This commit is contained in:
parent
8b1757eee2
commit
4ff4fa643b
9 changed files with 121 additions and 185 deletions
|
@ -32,7 +32,7 @@ struct FRemapTable
|
|||
PalEntry Palette[256]; // The ideal palette this maps to
|
||||
int crc32;
|
||||
int Index;
|
||||
int NumEntries; // # of elements in this table (usually 256), if this is -1 it is a luminosity translation.
|
||||
int NumEntries; // # of elements in this table (usually 256)
|
||||
bool Inactive = false; // This table is inactive and should be treated as if it was passed as NULL
|
||||
bool TwodOnly = false; // Only used for 2D rendering
|
||||
bool ForFont = false; // Mark font translations because they may require different handling than the ones for sprites-
|
||||
|
|
|
@ -83,7 +83,6 @@ FFont::FFont (const char *name, const char *nametemplate, const char *filetempla
|
|||
Next = FirstFont;
|
||||
FirstFont = this;
|
||||
Cursor = '_';
|
||||
ActiveColors = 0;
|
||||
SpaceWidth = 0;
|
||||
FontHeight = 0;
|
||||
uint8_t pp = 0;
|
||||
|
@ -590,61 +589,6 @@ void FFont::RecordAllTextureColors(uint32_t *usedcolors)
|
|||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// SetDefaultTranslation
|
||||
//
|
||||
// Builds a translation to map the stock font to a mod provided replacement.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void FFont::SetDefaultTranslation(uint32_t *othercolors)
|
||||
{
|
||||
uint32_t mycolors[256] = {};
|
||||
RecordAllTextureColors(mycolors);
|
||||
|
||||
uint8_t mytranslation[256], othertranslation[256], myreverse[256], otherreverse[256];
|
||||
TArray<double> myluminosity, otherluminosity;
|
||||
|
||||
SimpleTranslation(mycolors, mytranslation, myreverse, myluminosity);
|
||||
SimpleTranslation(othercolors, othertranslation, otherreverse, otherluminosity);
|
||||
|
||||
FRemapTable remap(ActiveColors);
|
||||
remap.Remap[0] = 0;
|
||||
remap.Palette[0] = 0;
|
||||
remap.ForFont = true;
|
||||
|
||||
for (unsigned l = 1; l < myluminosity.Size(); l++)
|
||||
{
|
||||
for (unsigned o = 1; o < otherluminosity.Size()-1; o++) // luminosity[0] is for the transparent color
|
||||
{
|
||||
if (myluminosity[l] >= otherluminosity[o] && myluminosity[l] <= otherluminosity[o+1])
|
||||
{
|
||||
PalEntry color1 = GPalette.BaseColors[otherreverse[o]];
|
||||
PalEntry color2 = GPalette.BaseColors[otherreverse[o+1]];
|
||||
double weight = 0;
|
||||
if (otherluminosity[o] != otherluminosity[o + 1])
|
||||
{
|
||||
weight = (myluminosity[l] - otherluminosity[o]) / (otherluminosity[o + 1] - otherluminosity[o]);
|
||||
}
|
||||
int r = int(color1.r + weight * (color2.r - color1.r));
|
||||
int g = int(color1.g + weight * (color2.g - color1.g));
|
||||
int b = int(color1.b + weight * (color2.b - color1.b));
|
||||
|
||||
r = clamp(r, 0, 255);
|
||||
g = clamp(g, 0, 255);
|
||||
b = clamp(b, 0, 255);
|
||||
remap.Remap[l] = ColorMatcher.Pick(r, g, b);
|
||||
remap.Palette[l] = PalEntry(255, r, g, b);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
Translations[CR_UNTRANSLATED] = GPalette.StoreTranslation(TRANSLATION_Internal, &remap);
|
||||
forceremap = true;
|
||||
}
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// compare
|
||||
|
@ -668,66 +612,40 @@ static int compare (const void *arg1, const void *arg2)
|
|||
|
||||
//==========================================================================
|
||||
//
|
||||
// FFont :: SimpleTranslation
|
||||
//
|
||||
// Colorsused, translation, and reverse must all be 256 entry buffers.
|
||||
// Colorsused must already be filled out.
|
||||
// Translation be set to remap the source colors to a new range of
|
||||
// consecutive colors based at 1 (0 is transparent).
|
||||
// Reverse will be just the opposite of translation: It maps the new color
|
||||
// range to the original colors.
|
||||
// *Luminosity will be an array just large enough to hold the brightness
|
||||
// levels of all the used colors, in consecutive order. It is sorted from
|
||||
// darkest to lightest and scaled such that the darkest color is 0.0 and
|
||||
// the brightest color is 1.0.
|
||||
// The return value is the number of used colors and thus the number of
|
||||
// entries in *luminosity.
|
||||
// FFont :: GetLuminosity
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
int FFont::SimpleTranslation (uint32_t *colorsused, uint8_t *translation, uint8_t *reverse, TArray<double> &Luminosity, int* minlum, int* maxlum)
|
||||
int FFont::GetLuminosity (uint32_t *colorsused, TArray<double> &Luminosity, int* minlum, int* maxlum)
|
||||
{
|
||||
double min, max, diver;
|
||||
int i, j;
|
||||
|
||||
memset (translation, 0, 256);
|
||||
|
||||
reverse[0] = 0;
|
||||
for (i = 1, j = 1; i < 256; i++)
|
||||
{
|
||||
if (colorsused[i])
|
||||
{
|
||||
reverse[j++] = i;
|
||||
}
|
||||
}
|
||||
|
||||
qsort (reverse+1, j-1, 1, compare);
|
||||
|
||||
Luminosity.Resize(j);
|
||||
Luminosity.Resize(256);
|
||||
Luminosity[0] = 0.0; // [BL] Prevent uninitalized memory
|
||||
max = 0.0;
|
||||
min = 100000000.0;
|
||||
for (i = 1; i < j; i++)
|
||||
for (int i = 1; i < 256; i++)
|
||||
{
|
||||
translation[reverse[i]] = i;
|
||||
|
||||
Luminosity[i] = RPART(GPalette.BaseColors[reverse[i]]) * 0.299 +
|
||||
GPART(GPalette.BaseColors[reverse[i]]) * 0.587 +
|
||||
BPART(GPalette.BaseColors[reverse[i]]) * 0.114;
|
||||
if (Luminosity[i] > max)
|
||||
max = Luminosity[i];
|
||||
if (Luminosity[i] < min)
|
||||
min = Luminosity[i];
|
||||
if (colorsused[i])
|
||||
{
|
||||
Luminosity[i] = GPalette.BaseColors[i].r * 0.299 + GPalette.BaseColors[i].g * 0.587 + GPalette.BaseColors[i].b * 0.114;
|
||||
if (Luminosity[i] > max) max = Luminosity[i];
|
||||
if (Luminosity[i] < min) min = Luminosity[i];
|
||||
}
|
||||
else Luminosity[i] = -1; // this color is not of interest.
|
||||
}
|
||||
diver = 1.0 / (max - min);
|
||||
for (i = 1; i < j; i++)
|
||||
for (int i = 1; i < 256; i++)
|
||||
{
|
||||
Luminosity[i] = (Luminosity[i] - min) * diver;
|
||||
if (colorsused[i])
|
||||
{
|
||||
Luminosity[i] = (Luminosity[i] - min) * diver;
|
||||
}
|
||||
}
|
||||
if (minlum) *minlum = int(min);
|
||||
if (maxlum) *maxlum = int(max);
|
||||
|
||||
return j;
|
||||
return 256;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
@ -748,7 +666,7 @@ int FFont::GetColorTranslation (EColorRange range, PalEntry *color) const
|
|||
}
|
||||
if (color != nullptr) *color = retcolor;
|
||||
}
|
||||
if (ActiveColors == 0 || range == CR_UNDEFINED)
|
||||
if (range == CR_UNDEFINED)
|
||||
return -1;
|
||||
else if (range >= NumTextColors)
|
||||
range = CR_UNTRANSLATED;
|
||||
|
@ -1046,7 +964,6 @@ void FFont::LoadTranslations()
|
|||
{
|
||||
unsigned int count = LastChar - FirstChar + 1;
|
||||
uint32_t usedcolors[256] = {};
|
||||
uint8_t identity[256];
|
||||
TArray<double> Luminosity;
|
||||
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
|
@ -1059,7 +976,7 @@ void FFont::LoadTranslations()
|
|||
}
|
||||
|
||||
int minlum = 0, maxlum = 0;
|
||||
ActiveColors = SimpleTranslation (usedcolors, PatchRemap, identity, Luminosity, &minlum, &maxlum);
|
||||
GetLuminosity (usedcolors, Luminosity, &minlum, &maxlum);
|
||||
|
||||
// Here we can set everything to a luminosity translation.
|
||||
|
||||
|
@ -1068,7 +985,7 @@ void FFont::LoadTranslations()
|
|||
for (int i = 0; i < NumTextColors; i++)
|
||||
{
|
||||
if (i == CR_UNTRANSLATED) Translations[i] = 0;
|
||||
else Translations[i] = LuminosityTranslation(i*2, minlum, maxlum);
|
||||
else Translations[i] = LuminosityTranslation(i*2 + TranslationType, minlum, maxlum);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -395,58 +395,6 @@ public:
|
|||
else Translations[i] = LuminosityTranslation(i * 2, minlum, maxlum);
|
||||
}
|
||||
}
|
||||
|
||||
void SetDefaultTranslation(uint32_t *colors) override
|
||||
{
|
||||
double myluminosity[18];
|
||||
|
||||
myluminosity[0] = 0;
|
||||
for (int i = 1; i < 18; i++)
|
||||
{
|
||||
myluminosity[i] = (i - 1) / 16.;
|
||||
}
|
||||
|
||||
uint8_t othertranslation[256], otherreverse[256];
|
||||
TArray<double> otherluminosity;
|
||||
|
||||
SimpleTranslation(colors, othertranslation, otherreverse, otherluminosity);
|
||||
|
||||
FRemapTable remap(ActiveColors);
|
||||
remap.Remap[0] = 0;
|
||||
remap.Palette[0] = 0;
|
||||
remap.ForFont = true;
|
||||
|
||||
for (unsigned l = 1; l < 18; l++)
|
||||
{
|
||||
for (unsigned o = 1; o < otherluminosity.Size() - 1; o++) // luminosity[0] is for the transparent color
|
||||
{
|
||||
if (myluminosity[l] >= otherluminosity[o] && myluminosity[l] <= otherluminosity[o + 1])
|
||||
{
|
||||
PalEntry color1 = GPalette.BaseColors[otherreverse[o]];
|
||||
PalEntry color2 = GPalette.BaseColors[otherreverse[o + 1]];
|
||||
double weight = 0;
|
||||
if (otherluminosity[o] != otherluminosity[o + 1])
|
||||
{
|
||||
weight = (myluminosity[l] - otherluminosity[o]) / (otherluminosity[o + 1] - otherluminosity[o]);
|
||||
}
|
||||
int r = int(color1.r + weight * (color2.r - color1.r));
|
||||
int g = int(color1.g + weight * (color2.g - color1.g));
|
||||
int b = int(color1.b + weight * (color2.b - color1.b));
|
||||
|
||||
r = clamp(r, 0, 255);
|
||||
g = clamp(g, 0, 255);
|
||||
b = clamp(b, 0, 255);
|
||||
remap.Remap[l] = ColorMatcher.Pick(r, g, b);
|
||||
remap.Palette[l] = PalEntry(255, r, g, b);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
Translations[CR_UNTRANSLATED] = GPalette.StoreTranslation(TRANSLATION_Internal, &remap);
|
||||
forceremap = true;
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -105,6 +105,7 @@ protected:
|
|||
} FontType;
|
||||
PalEntry Palette[256];
|
||||
bool RescalePalette;
|
||||
int ActiveColors = -1;
|
||||
};
|
||||
|
||||
|
||||
|
@ -468,7 +469,7 @@ void FSingleLumpFont::LoadBMF(int lump, const uint8_t *data)
|
|||
// FSingleLumpFont :: CheckFON1Chars
|
||||
//
|
||||
// Scans a FON1 resource for all the color values it uses and sets up
|
||||
// some tables like SimpleTranslation. Data points to the RLE data for
|
||||
// some tables. Data points to the RLE data for
|
||||
// the characters. Also sets up the character textures.
|
||||
//
|
||||
//==========================================================================
|
||||
|
|
|
@ -79,7 +79,6 @@ FSinglePicFont::FSinglePicFont(const char *picname) :
|
|||
SpaceWidth = (int)pic->GetDisplayWidth();
|
||||
GlobalKerning = 0;
|
||||
FirstChar = LastChar = 'A';
|
||||
ActiveColors = 0;
|
||||
PicNum = picnum;
|
||||
|
||||
Next = FirstFont;
|
||||
|
|
|
@ -129,11 +129,6 @@ FSpecialFont::FSpecialFont (const char *name, int first, int count, FGameTexture
|
|||
}
|
||||
|
||||
FixXMoves();
|
||||
|
||||
if (noTranslate)
|
||||
{
|
||||
ActiveColors = 0;
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
|
|
@ -687,6 +687,75 @@ void V_ApplyLuminosityTranslation(int translation, uint8_t* pixel, int size)
|
|||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// SetDefaultTranslation
|
||||
//
|
||||
// Builds a translation to map the stock font to a mod provided replacement.
|
||||
// This probably won't work that well if the original font is extremely colorful.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
static void CalcDefaultTranslation(FFont* base, int index)
|
||||
{
|
||||
uint32_t othercolors[256] = {};
|
||||
base->RecordAllTextureColors(othercolors);
|
||||
|
||||
TArray<double> otherluminosity;
|
||||
base->GetLuminosity(othercolors, otherluminosity);
|
||||
|
||||
PalEntry *remap = &paletteptr[index * 256];
|
||||
memset(remap, 0, 1024);
|
||||
|
||||
for (unsigned i = 0; i < 256; i++)
|
||||
{
|
||||
auto lum = otherluminosity[i];
|
||||
if (lum >= 0 && lum <= 1)
|
||||
{
|
||||
int index = int(lum * 255);
|
||||
remap[index] = GPalette.BaseColors[i];
|
||||
}
|
||||
}
|
||||
|
||||
// todo: fill the gaps.
|
||||
remap[0] = 0;
|
||||
int lowindex = 0;
|
||||
int highindex = 1;
|
||||
|
||||
while (lowindex < 255)
|
||||
{
|
||||
while (highindex <= 255 && remap[highindex].a == 0) highindex++;
|
||||
if (lowindex == 0)
|
||||
{
|
||||
for (int i = 0; i < highindex; i++) remap[i] = remap[highindex];
|
||||
lowindex = highindex++;
|
||||
}
|
||||
else if (highindex > 256)
|
||||
{
|
||||
for (int i = lowindex + 1; i < highindex; i++) remap[i] = remap[lowindex];
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = lowindex + 1; i < highindex; i++)
|
||||
{
|
||||
PalEntry color1 = remap[lowindex];
|
||||
PalEntry color2 = remap[highindex];
|
||||
double weight = (i - lowindex) / double(highindex - lowindex);
|
||||
int r = int(color1.r + weight * (color2.r - color1.r));
|
||||
int g = int(color1.g + weight * (color2.g - color1.g));
|
||||
int b = int(color1.b + weight * (color2.b - color1.b));
|
||||
r = clamp(r, 0, 255);
|
||||
g = clamp(g, 0, 255);
|
||||
b = clamp(b, 0, 255);
|
||||
remap[i] = PalEntry(255, r, g, b);
|
||||
}
|
||||
lowindex = highindex++;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// V_LogColorFromColorRange
|
||||
|
@ -929,24 +998,44 @@ void V_LoadTranslations()
|
|||
for (auto font = FFont::FirstFont; font; font = font->Next)
|
||||
{
|
||||
if (!font->noTranslate) font->LoadTranslations();
|
||||
else font->ActiveColors = 0;
|
||||
}
|
||||
|
||||
if (BigFont)
|
||||
{
|
||||
uint32_t colors[256] = {};
|
||||
BigFont->RecordAllTextureColors(colors);
|
||||
if (OriginalBigFont != nullptr) OriginalBigFont->SetDefaultTranslation(colors);
|
||||
CalcDefaultTranslation(BigFont, CR_UNTRANSLATED * 2 + 1);
|
||||
if (OriginalBigFont != nullptr && OriginalBigFont != BigFont)
|
||||
{
|
||||
int sometrans = OriginalBigFont->Translations[0];
|
||||
sometrans &= ~(0x3fff << 16);
|
||||
sometrans |= (CR_UNTRANSLATED * 2 + 1) << 16;
|
||||
OriginalBigFont->Translations[CR_UNTRANSLATED] = sometrans;
|
||||
OriginalBigFont->forceremap = true;
|
||||
}
|
||||
}
|
||||
if (SmallFont)
|
||||
{
|
||||
uint32_t colors[256] = {};
|
||||
SmallFont->RecordAllTextureColors(colors);
|
||||
if (OriginalSmallFont != nullptr) OriginalSmallFont->SetDefaultTranslation(colors);
|
||||
NewSmallFont->SetDefaultTranslation(colors);
|
||||
CalcDefaultTranslation(SmallFont, CR_UNTRANSLATED * 2);
|
||||
if (OriginalSmallFont != nullptr && OriginalSmallFont != SmallFont)
|
||||
{
|
||||
int sometrans = OriginalSmallFont->Translations[0];
|
||||
sometrans &= ~(0x3fff << 16);
|
||||
sometrans |= (CR_UNTRANSLATED * 2) << 16;
|
||||
OriginalSmallFont->Translations[CR_UNTRANSLATED] = sometrans;
|
||||
OriginalSmallFont->forceremap = true;
|
||||
}
|
||||
if (NewSmallFont != nullptr)
|
||||
{
|
||||
int sometrans = NewSmallFont->Translations[0];
|
||||
sometrans &= ~(0x3fff << 16);
|
||||
sometrans |= (CR_UNTRANSLATED * 2) << 16;
|
||||
NewSmallFont->Translations[CR_UNTRANSLATED] = sometrans;
|
||||
NewSmallFont->forceremap = true;
|
||||
}
|
||||
}
|
||||
translationsLoaded = true;
|
||||
}
|
||||
|
||||
|
||||
void V_ClearFonts()
|
||||
{
|
||||
while (FFont::FirstFont != nullptr)
|
||||
|
|
|
@ -128,20 +128,17 @@ public:
|
|||
void SetKerning(int c) { GlobalKerning = c; }
|
||||
bool NoTranslate() const { return noTranslate; }
|
||||
virtual void RecordAllTextureColors(uint32_t *usedcolors);
|
||||
virtual void SetDefaultTranslation(uint32_t *colors);
|
||||
void CheckCase();
|
||||
|
||||
int GetDisplacement() const { return Displacement; }
|
||||
|
||||
static int GetLuminosity(uint32_t* colorsused, TArray<double>& Luminosity, int* minlum = nullptr, int* maxlum = nullptr);
|
||||
|
||||
protected:
|
||||
FFont (int lump);
|
||||
|
||||
void FixXMoves();
|
||||
|
||||
static int SimpleTranslation (uint32_t *colorsused, uint8_t *translation,
|
||||
uint8_t *identity, TArray<double> &Luminosity, int* minlum = nullptr, int* maxlum = nullptr);
|
||||
|
||||
void ReadSheetFont(TArray<FolderEntry> &folderdata, int width, int height, const DVector2 &Scale);
|
||||
|
||||
EFontType Type = EFontType::Unknown;
|
||||
|
@ -163,7 +160,6 @@ protected:
|
|||
int XMove = INT_MIN;
|
||||
};
|
||||
TArray<CharData> Chars;
|
||||
int ActiveColors = -1;
|
||||
TArray<int> Translations;
|
||||
uint8_t PatchRemap[256];
|
||||
|
||||
|
|
|
@ -186,15 +186,6 @@ void UpdateStatusBar(SummaryInfo* info)
|
|||
VMValue params[] = { StatusBar, info };
|
||||
VMCall(func, params, 2, nullptr, 0);
|
||||
}
|
||||
|
||||
#if 1 // for testing.
|
||||
for (int i = 0; i < NumTextColors; i++)
|
||||
{
|
||||
FStringf buffer("This is font color %d", i);
|
||||
DrawText(twod, BigFont, i, 340, i * 15, buffer, DTA_FullscreenScale, FSMode_Fit640x400, TAG_DONE);
|
||||
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void TickStatusBar()
|
||||
|
|
Loading…
Reference in a new issue