- use luminosity translations for single lump fonts and let them use their original palette.

This commit is contained in:
Christoph Oelckers 2021-05-24 17:04:07 +02:00
parent 377829d6a2
commit 372d425e01
4 changed files with 90 additions and 198 deletions

View file

@ -90,17 +90,12 @@ public:
void RecordAllTextureColors(uint32_t* usedcolors) override; void RecordAllTextureColors(uint32_t* usedcolors) override;
protected: protected:
void CheckFON1Chars (double *luminosity); void CheckFON1Chars ();
void BuildTranslations2 (); void FixupPalette (uint8_t *identity, const PalEntry *palette, int* minlum ,int* maxlum);
void FixupPalette (uint8_t *identity, double *luminosity, const uint8_t *palette,
bool rescale, PalEntry *out_palette);
void LoadTranslations (); void LoadTranslations ();
void LoadFON1 (int lump, const uint8_t *data); void LoadFON1 (int lump, const uint8_t *data);
void LoadFON2 (int lump, const uint8_t *data); void LoadFON2 (int lump, const uint8_t *data);
void LoadBMF (int lump, const uint8_t *data); void LoadBMF (int lump, const uint8_t *data);
void CreateFontFromPic (FTextureID picnum);
static int BMFCompare(const void *a, const void *b);
enum enum
{ {
@ -108,7 +103,7 @@ protected:
FONT2, FONT2,
BMFFONT BMFFONT
} FontType; } FontType;
uint8_t PaletteData[768]; PalEntry Palette[256];
bool RescalePalette; bool RescalePalette;
}; };
@ -160,29 +155,6 @@ FSingleLumpFont::FSingleLumpFont (const char *name, int lump) : FFont(lump)
FirstFont = this; FirstFont = this;
} }
//==========================================================================
//
// FSingleLumpFont :: CreateFontFromPic
//
//==========================================================================
void FSingleLumpFont::CreateFontFromPic (FTextureID picnum)
{
auto pic = TexMan.GetGameTexture(picnum);
FontHeight = (int)pic->GetDisplayHeight ();
SpaceWidth = (int)pic->GetDisplayWidth ();
GlobalKerning = 0;
FirstChar = LastChar = 'A';
Chars.Resize(1);
Chars[0].TranslatedPic = pic;
Chars[0].OriginalPic = pic;
// Only one color range. Don't bother with the others.
ActiveColors = 0;
}
//========================================================================== //==========================================================================
// //
// FSingleLumpFont :: LoadTranslations // FSingleLumpFont :: LoadTranslations
@ -191,28 +163,21 @@ void FSingleLumpFont::CreateFontFromPic (FTextureID picnum)
void FSingleLumpFont::LoadTranslations() void FSingleLumpFont::LoadTranslations()
{ {
double luminosity[256];
uint8_t identity[256]; uint8_t identity[256];
PalEntry local_palette[256];
bool useidentity = true;
bool usepalette = false;
const void* ranges;
unsigned int count = LastChar - FirstChar + 1; unsigned int count = LastChar - FirstChar + 1;
int minlum, maxlum;
switch(FontType) switch(FontType)
{ {
case FONT1: case FONT1:
useidentity = false; CheckFON1Chars();
ranges = &TranslationParms[1][0]; minlum = 1;
CheckFON1Chars (luminosity); maxlum = 255;
break; break;
case BMFFONT: case BMFFONT:
case FONT2: case FONT2:
usepalette = true; FixupPalette (identity, Palette, &minlum, &maxlum);
FixupPalette (identity, luminosity, PaletteData, RescalePalette, local_palette);
ranges = &TranslationParms[0][0];
break; break;
default: default:
@ -224,10 +189,15 @@ void FSingleLumpFont::LoadTranslations()
for(unsigned int i = 0;i < count;++i) for(unsigned int i = 0;i < count;++i)
{ {
if(Chars[i].TranslatedPic) if(Chars[i].TranslatedPic)
static_cast<FFontChar2*>(Chars[i].TranslatedPic->GetTexture()->GetImage())->SetSourceRemap(PatchRemap); static_cast<FFontChar2*>(Chars[i].TranslatedPic->GetTexture()->GetImage())->SetSourceRemap(Palette);
} }
BuildTranslations (luminosity, useidentity ? identity : nullptr, ranges, ActiveColors, usepalette ? local_palette : nullptr); Translations.Resize(NumTextColors);
for (int i = 0; i < NumTextColors; i++)
{
if (i == CR_UNTRANSLATED) Translations[i] = 0;
else Translations[i] = LuminosityTranslation(i * 2 + (FontType == FONT1 ? 1 : 0), minlum, maxlum);
}
} }
//========================================================================== //==========================================================================
@ -262,19 +232,20 @@ void FSingleLumpFont::LoadFON1 (int lump, const uint8_t *data)
// Move the Windows-1252 characters to their proper place. // Move the Windows-1252 characters to their proper place.
for (int i = 0x80; i < 0xa0; i++) for (int i = 0x80; i < 0xa0; i++)
{ {
if (win1252map[i-0x80] != i && Chars[i].TranslatedPic != nullptr && Chars[win1252map[i - 0x80]].TranslatedPic == nullptr) if (win1252map[i-0x80] != i && Chars[i].OriginalPic != nullptr && Chars[win1252map[i - 0x80]].OriginalPic == nullptr)
{ {
std::swap(Chars[i], Chars[win1252map[i - 0x80]]); std::swap(Chars[i], Chars[win1252map[i - 0x80]]);
} }
} }
Palette[0] = 0;
for (int i = 1; i < 256; i++) Palette[i] = PalEntry(255, i, i, i);
} }
//========================================================================== //==========================================================================
// //
// FSingleLumpFont :: LoadFON2 // FSingleLumpFont :: LoadFON2
// //
// FON2 is used for everything but the console font. The console font should // FON2 is used for everything but the console font.
// probably use FON2 as well, but oh well.
// //
//========================================================================== //==========================================================================
@ -340,7 +311,11 @@ void FSingleLumpFont::LoadFON2 (int lump, const uint8_t *data)
SpaceWidth = totalwidth * 2 / (3 * count); SpaceWidth = totalwidth * 2 / (3 * count);
} }
memcpy(PaletteData, palette, ActiveColors*3); Palette[0] = 0;
for (int i = 1; i < ActiveColors; i++)
{
Palette[i] = PalEntry(255, palette[i * 3], palette[i * 3 + 1], palette[i * 3 + 2]);
}
data_p = palette + ActiveColors*3; data_p = palette + ActiveColors*3;
@ -396,8 +371,6 @@ void FSingleLumpFont::LoadBMF(int lump, const uint8_t *data)
int numchars, count, totalwidth, nwidth; int numchars, count, totalwidth, nwidth;
int infolen; int infolen;
int i, chari; int i, chari;
uint8_t raw_palette[256*3];
PalEntry sort_palette[256];
FontType = BMFFONT; FontType = BMFFONT;
FontHeight = data[5]; FontHeight = data[5];
@ -439,31 +412,14 @@ void FSingleLumpFont::LoadBMF(int lump, const uint8_t *data)
count = LastChar - FirstChar + 1; count = LastChar - FirstChar + 1;
Chars.Resize(count); Chars.Resize(count);
// BMF palettes are only six bits per component. Fix that. // BMF palettes are only six bits per component. Fix that.
for (i = 0; i < ActiveColors*3; ++i)
{
raw_palette[i+3] = (data[17 + i] << 2) | (data[17 + i] >> 4);
}
ActiveColors++;
// Sort the palette by increasing brightness
for (i = 0; i < ActiveColors; ++i) for (i = 0; i < ActiveColors; ++i)
{ {
PalEntry *pal = &sort_palette[i]; int r = (data[17 + i * 3] << 2) | (data[17 + i * 3] >> 4);
pal->a = i; // Use alpha part to point back to original entry int g = (data[18 + i * 3] << 2) | (data[18 + i * 3] >> 4);
pal->r = raw_palette[i*3 + 0]; int b = (data[19 + i * 3] << 2) | (data[19 + i * 3] >> 4);
pal->g = raw_palette[i*3 + 1]; Palette[i + 1] = PalEntry(255, r, g, b); // entry 0 (transparent) is not stored in the font file.
pal->b = raw_palette[i*3 + 2];
} }
qsort(sort_palette + 1, ActiveColors - 1, sizeof(PalEntry), BMFCompare); ActiveColors++;
// Create the PatchRemap table from the sorted "alpha" values.
PatchRemap[0] = 0;
for (i = 1; i < ActiveColors; ++i)
{
PatchRemap[sort_palette[i].a] = i;
}
memcpy(PaletteData, raw_palette, 768);
// Now scan through the characters again, creating glyphs for each one. // Now scan through the characters again, creating glyphs for each one.
for (i = chari = 0; i < numchars; ++i, chari += 6 + chardata[chari+1] * chardata[chari+2]) for (i = chari = 0; i < numchars; ++i, chari += 6 + chardata[chari+1] * chardata[chari+2])
@ -510,23 +466,6 @@ void FSingleLumpFont::LoadBMF(int lump, const uint8_t *data)
FixXMoves(); FixXMoves();
} }
//==========================================================================
//
// FSingleLumpFont :: BMFCompare STATIC
//
// Helper to sort BMF palettes.
//
//==========================================================================
int FSingleLumpFont::BMFCompare(const void *a, const void *b)
{
const PalEntry *pa = (const PalEntry *)a;
const PalEntry *pb = (const PalEntry *)b;
return (pa->r * 299 + pa->g * 587 + pa->b * 114) -
(pb->r * 299 + pb->g * 587 + pb->b * 114);
}
//========================================================================== //==========================================================================
// //
// FSingleLumpFont :: CheckFON1Chars // FSingleLumpFont :: CheckFON1Chars
@ -537,25 +476,21 @@ int FSingleLumpFont::BMFCompare(const void *a, const void *b)
// //
//========================================================================== //==========================================================================
void FSingleLumpFont::CheckFON1Chars (double *luminosity) void FSingleLumpFont::CheckFON1Chars()
{ {
FileData memLump = fileSystem.ReadFile(Lump); FileData memLump = fileSystem.ReadFile(Lump);
const uint8_t* data = (const uint8_t*) memLump.GetMem(); const uint8_t* data = (const uint8_t*)memLump.GetMem();
const uint8_t* data_p;
uint8_t used[256], reverse[256];
const uint8_t *data_p;
int i, j;
memset (used, 0, 256);
data_p = data + 8; data_p = data + 8;
for (i = 0; i < 256; ++i) for (int i = 0; i < 256; ++i)
{ {
int destSize = SpaceWidth * FontHeight; int destSize = SpaceWidth * FontHeight;
if(!Chars[i].TranslatedPic) if (!Chars[i].TranslatedPic)
{ {
Chars[i].TranslatedPic = MakeGameTexture(new FImageTexture(new FFontChar2 (Lump, int(data_p - data), SpaceWidth, FontHeight)), nullptr, ETextureType::FontChar); Chars[i].TranslatedPic = MakeGameTexture(new FImageTexture(new FFontChar2(Lump, int(data_p - data), SpaceWidth, FontHeight)), nullptr, ETextureType::FontChar);
Chars[i].OriginalPic = Chars[i].TranslatedPic; Chars[i].OriginalPic = Chars[i].TranslatedPic;
Chars[i].XMove = SpaceWidth; Chars[i].XMove = SpaceWidth;
TexMan.AddGameTexture(Chars[i].TranslatedPic); TexMan.AddGameTexture(Chars[i].TranslatedPic);
@ -567,87 +502,52 @@ void FSingleLumpFont::CheckFON1Chars (double *luminosity)
int8_t code = *data_p++; int8_t code = *data_p++;
if (code >= 0) if (code >= 0)
{ {
destSize -= code+1; destSize -= code + 1;
while (code-- >= 0) while (code-- >= 0)
{ {
used[*data_p++] = 1; data_p++;
} }
} }
else if (code != -128) else if (code != -128)
{ {
used[*data_p++] = 1; data_p++;
destSize -= 1 - code; destSize -= 1 - code;
} }
} while (destSize > 0); } while (destSize > 0);
} }
ActiveColors = 256;
memset (PatchRemap, 0, 256);
reverse[0] = 0;
for (i = 1, j = 1; i < 256; ++i)
{
if (used[i])
{
reverse[j++] = i;
}
}
for (i = 1; i < j; ++i)
{
PatchRemap[reverse[i]] = i;
luminosity[i] = (reverse[i] - 1) / 254.0;
}
ActiveColors = j;
} }
//========================================================================== //==========================================================================
// //
// FSingleLumpFont :: FixupPalette // FSingleLumpFont :: FixupPalette
// //
// Finds the best matches for the colors used by a FON2 font and sets up // Finds the best matches for the colors used by a FON2 font and finds thr
// some tables like SimpleTranslation. // used luminosity range
// //
//========================================================================== //==========================================================================
void FSingleLumpFont::FixupPalette (uint8_t *identity, double *luminosity, const uint8_t *palette, bool rescale, PalEntry *out_palette) void FSingleLumpFont::FixupPalette (uint8_t *identity, const PalEntry *palette, int *pminlum, int *pmaxlum)
{ {
int i;
double maxlum = 0.0; double maxlum = 0.0;
double minlum = 100000000.0; double minlum = 100000000.0;
double diver;
identity[0] = 0; identity[0] = 0;
palette += 3; // Skip the transparent color palette += 3; // Skip the transparent color
for (i = 1; i < ActiveColors; ++i, palette += 3) for (int i = 1; i < ActiveColors; ++i, palette ++)
{ {
int r = palette[0]; int r = palette->r;
int g = palette[1]; int g = palette->g;
int b = palette[2]; int b = palette->b;
double lum = r*0.299 + g*0.587 + b*0.114; double lum = r*0.299 + g*0.587 + b*0.114;
identity[i] = ColorMatcher.Pick(r, g, b); identity[i] = ColorMatcher.Pick(r, g, b);
luminosity[i] = lum; if (lum > maxlum) maxlum = lum;
out_palette[i].r = r; if (lum < minlum) minlum = lum;
out_palette[i].g = g;
out_palette[i].b = b;
out_palette[i].a = 255;
if (lum > maxlum)
maxlum = lum;
if (lum < minlum)
minlum = lum;
} }
out_palette[0] = 0;
if (rescale) if (pminlum) *pminlum = int(minlum);
{ if (pmaxlum) *pmaxlum = int(maxlum);
diver = 1.0 / (maxlum - minlum);
}
else
{
diver = 1.0 / 255.0;
}
for (i = 1; i < ActiveColors; ++i)
{
luminosity[i] = (luminosity[i] - minlum) * diver;
}
} }
//========================================================================== //==========================================================================
@ -661,13 +561,11 @@ void FSingleLumpFont::FixupPalette (uint8_t *identity, double *luminosity, const
void FSingleLumpFont::RecordAllTextureColors(uint32_t* usedcolors) void FSingleLumpFont::RecordAllTextureColors(uint32_t* usedcolors)
{ {
double luminosity[256];
uint8_t identity[256]; uint8_t identity[256];
PalEntry local_palette[256];
if (FontType == BMFFONT || FontType == FONT2) if (FontType == BMFFONT || FontType == FONT2)
{ {
FixupPalette(identity, luminosity, PaletteData, RescalePalette, local_palette); FixupPalette(identity, Palette, nullptr, nullptr);
for (int i = 0; i < 256; i++) for (int i = 0; i < 256; i++)
{ {
if (identity[i] != 0) usedcolors[identity[i]]++; if (identity[i] != 0) usedcolors[identity[i]]++;

View file

@ -49,8 +49,8 @@
// //
//========================================================================== //==========================================================================
FFontChar1::FFontChar1 (FImageSource *sourcelump) FFontChar1::FFontChar1(FImageSource* sourcelump)
: BaseTexture(sourcelump), SourceRemap (nullptr) : BaseTexture(sourcelump), SourceRemap(nullptr)
{ {
// now copy all the properties from the base texture // now copy all the properties from the base texture
assert(BaseTexture != nullptr); assert(BaseTexture != nullptr);
@ -66,7 +66,7 @@ FFontChar1::FFontChar1 (FImageSource *sourcelump)
// //
//========================================================================== //==========================================================================
TArray<uint8_t> FFontChar1::CreatePalettedPixels (int) TArray<uint8_t> FFontChar1::CreatePalettedPixels(int)
{ {
// Make the texture as normal, then remap it so that all the colors // Make the texture as normal, then remap it so that all the colors
// are at the low end of the palette // are at the low end of the palette
@ -75,7 +75,7 @@ TArray<uint8_t> FFontChar1::CreatePalettedPixels (int)
if (SourceRemap) if (SourceRemap)
{ {
for (int x = 0; x < Width*Height; ++x) for (int x = 0; x < Width * Height; ++x)
{ {
Pixels[x] = SourceRemap[Pixels[x]]; Pixels[x] = SourceRemap[Pixels[x]];
} }
@ -91,8 +91,8 @@ TArray<uint8_t> FFontChar1::CreatePalettedPixels (int)
// //
//========================================================================== //==========================================================================
FFontChar2::FFontChar2 (int sourcelump, int sourcepos, int width, int height, int leftofs, int topofs) FFontChar2::FFontChar2(int sourcelump, int sourcepos, int width, int height, int leftofs, int topofs)
: SourceLump (sourcelump), SourcePos (sourcepos), SourceRemap(nullptr) : SourceLump(sourcelump), SourcePos(sourcepos)
{ {
Width = width; Width = width;
Height = height; Height = height;
@ -100,17 +100,6 @@ FFontChar2::FFontChar2 (int sourcelump, int sourcepos, int width, int height, in
TopOffset = topofs; TopOffset = topofs;
} }
//==========================================================================
//
// FFontChar2 :: SetSourceRemap
//
//==========================================================================
void FFontChar2::SetSourceRemap(const uint8_t *sourceremap)
{
SourceRemap = sourceremap;
}
//========================================================================== //==========================================================================
// //
// FFontChar2 :: Get8BitPixels // FFontChar2 :: Get8BitPixels
@ -121,7 +110,7 @@ void FFontChar2::SetSourceRemap(const uint8_t *sourceremap)
TArray<uint8_t> FFontChar2::CreatePalettedPixels(int) TArray<uint8_t> FFontChar2::CreatePalettedPixels(int)
{ {
auto lump = fileSystem.OpenFileReader (SourceLump); auto lump = fileSystem.OpenFileReader(SourceLump);
int destSize = Width * Height; int destSize = Width * Height;
uint8_t max = 255; uint8_t max = 255;
bool rle = true; bool rle = true;
@ -129,23 +118,23 @@ TArray<uint8_t> FFontChar2::CreatePalettedPixels(int)
// This is to "fix" bad fonts // This is to "fix" bad fonts
{ {
uint8_t buff[16]; uint8_t buff[16];
lump.Read (buff, 4); lump.Read(buff, 4);
if (buff[3] == '2') if (buff[3] == '2')
{ {
lump.Read (buff, 7); lump.Read(buff, 7);
max = buff[6]; max = buff[6];
lump.Seek (SourcePos - 11, FileReader::SeekCur); lump.Seek(SourcePos - 11, FileReader::SeekCur);
} }
else if (buff[3] == 0x1A) else if (buff[3] == 0x1A)
{ {
lump.Read(buff, 13); lump.Read(buff, 13);
max = buff[12] - 1; max = buff[12] - 1;
lump.Seek (SourcePos - 17, FileReader::SeekCur); lump.Seek(SourcePos - 17, FileReader::SeekCur);
rle = false; rle = false;
} }
else else
{ {
lump.Seek (SourcePos - 4, FileReader::SeekCur); lump.Seek(SourcePos - 4, FileReader::SeekCur);
} }
} }
@ -153,7 +142,7 @@ TArray<uint8_t> FFontChar2::CreatePalettedPixels(int)
int runlen = 0, setlen = 0; int runlen = 0, setlen = 0;
uint8_t setval = 0; // Shut up, GCC! uint8_t setval = 0; // Shut up, GCC!
uint8_t *dest_p = Pixels.Data(); uint8_t* dest_p = Pixels.Data();
int dest_adv = Height; int dest_adv = Height;
int dest_rew = destSize - 1; int dest_rew = destSize - 1;
@ -166,11 +155,7 @@ TArray<uint8_t> FFontChar2::CreatePalettedPixels(int)
if (runlen != 0) if (runlen != 0)
{ {
uint8_t color = lump.ReadUInt8(); uint8_t color = lump.ReadUInt8();
color = MIN (color, max); color = MIN(color, max);
if (SourceRemap != nullptr)
{
color = SourceRemap[color];
}
*dest_p = color; *dest_p = color;
dest_p += dest_adv; dest_p += dest_adv;
x--; x--;
@ -194,11 +179,7 @@ TArray<uint8_t> FFontChar2::CreatePalettedPixels(int)
{ {
uint8_t color = lump.ReadUInt8(); uint8_t color = lump.ReadUInt8();
setlen = (-code) + 1; setlen = (-code) + 1;
setval = MIN (color, max); setval = MIN(color, max);
if (SourceRemap != nullptr)
{
setval = SourceRemap[setval];
}
} }
} }
} }
@ -216,10 +197,6 @@ TArray<uint8_t> FFontChar2::CreatePalettedPixels(int)
{ {
color = max; color = max;
} }
if (SourceRemap != nullptr)
{
color = SourceRemap[color];
}
*dest_p = color; *dest_p = color;
dest_p += dest_adv; dest_p += dest_adv;
} }
@ -230,10 +207,17 @@ TArray<uint8_t> FFontChar2::CreatePalettedPixels(int)
if (destSize < 0) if (destSize < 0)
{ {
char name[9]; char name[9];
fileSystem.GetFileShortName (name, SourceLump); fileSystem.GetFileShortName(name, SourceLump);
name[8] = 0; name[8] = 0;
I_FatalError ("The font %s is corrupt", name); I_FatalError("The font %s is corrupt", name);
} }
return Pixels; return Pixels;
} }
int FFontChar2::CopyPixels(FBitmap* bmp, int conversion)
{
if (conversion == luminance) conversion = normal; // luminance images have no use as an RGB source.
auto ppix = CreatePalettedPixels(conversion);
bmp->CopyPixelData(0, 0, ppix.Data(), Width, Height, Height, 1, 0, SourceRemap, nullptr);
return 0;
}

View file

@ -23,10 +23,15 @@ public:
FFontChar2 (int sourcelump, int sourcepos, int width, int height, int leftofs=0, int topofs=0); FFontChar2 (int sourcelump, int sourcepos, int width, int height, int leftofs=0, int topofs=0);
TArray<uint8_t> CreatePalettedPixels(int conversion) override; TArray<uint8_t> CreatePalettedPixels(int conversion) override;
void SetSourceRemap(const uint8_t *sourceremap); int CopyPixels(FBitmap* bmp, int conversion);
void SetSourceRemap(const PalEntry* sourceremap)
{
SourceRemap = sourceremap;
}
protected: protected:
int SourceLump; int SourceLump;
int SourcePos; int SourcePos;
const uint8_t *SourceRemap; const PalEntry *SourceRemap;
}; };

View file

@ -191,8 +191,13 @@ void UpdateStatusBar(SummaryInfo* info)
for (int i = 0; i < NumTextColors; i++) for (int i = 0; i < NumTextColors; i++)
{ {
FStringf buffer("This is font color %d", i); FStringf buffer("This is font color %d", i);
DrawText(twod, SmallFont, i, 40, i * 15, buffer, DTA_FullscreenScale, FSMode_Fit640x400, TAG_DONE); //DrawText(twod, SmallFont, i, 40, i * 15, buffer, DTA_FullscreenScale, FSMode_Fit640x400, TAG_DONE);
DrawText(twod, NewSmallFont, i, 340, i * 15, buffer, DTA_FullscreenScale, FSMode_Fit640x400, TAG_DONE); //DrawText(twod, V_GetFont("doomfont"), i, 40, i * 15, buffer, DTA_FullscreenScale, FSMode_Fit640x400, TAG_DONE);
//DrawText(twod, NewSmallFont, i, 340, i * 15, buffer, DTA_FullscreenScale, FSMode_Fit640x400, TAG_DONE);
DrawText(twod, V_GetFont("condfont"), i, 40, i * 15, buffer, DTA_FullscreenScale, FSMode_Fit640x400, TAG_DONE);
DrawText(twod, NewConsoleFont, i, 340, i * 15, buffer, DTA_FullscreenScale, FSMode_Fit640x400, TAG_DONE);
} }
#endif #endif
} }