- 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,25 +90,20 @@ public:
void RecordAllTextureColors(uint32_t* usedcolors) override;
protected:
void CheckFON1Chars (double *luminosity);
void BuildTranslations2 ();
void FixupPalette (uint8_t *identity, double *luminosity, const uint8_t *palette,
bool rescale, PalEntry *out_palette);
void CheckFON1Chars ();
void FixupPalette (uint8_t *identity, const PalEntry *palette, int* minlum ,int* maxlum);
void LoadTranslations ();
void LoadFON1 (int lump, const uint8_t *data);
void LoadFON2 (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
{
FONT1,
FONT2,
BMFFONT
} FontType;
uint8_t PaletteData[768];
PalEntry Palette[256];
bool RescalePalette;
};
@ -160,29 +155,6 @@ FSingleLumpFont::FSingleLumpFont (const char *name, int lump) : FFont(lump)
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
@ -191,28 +163,21 @@ void FSingleLumpFont::CreateFontFromPic (FTextureID picnum)
void FSingleLumpFont::LoadTranslations()
{
double luminosity[256];
uint8_t identity[256];
PalEntry local_palette[256];
bool useidentity = true;
bool usepalette = false;
const void* ranges;
unsigned int count = LastChar - FirstChar + 1;
int minlum, maxlum;
switch(FontType)
{
case FONT1:
useidentity = false;
ranges = &TranslationParms[1][0];
CheckFON1Chars (luminosity);
CheckFON1Chars();
minlum = 1;
maxlum = 255;
break;
case BMFFONT:
case FONT2:
usepalette = true;
FixupPalette (identity, luminosity, PaletteData, RescalePalette, local_palette);
ranges = &TranslationParms[0][0];
FixupPalette (identity, Palette, &minlum, &maxlum);
break;
default:
@ -224,10 +189,15 @@ void FSingleLumpFont::LoadTranslations()
for(unsigned int i = 0;i < count;++i)
{
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.
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]]);
}
}
Palette[0] = 0;
for (int i = 1; i < 256; i++) Palette[i] = PalEntry(255, i, i, i);
}
//==========================================================================
//
// FSingleLumpFont :: LoadFON2
//
// FON2 is used for everything but the console font. The console font should
// probably use FON2 as well, but oh well.
// FON2 is used for everything but the console font.
//
//==========================================================================
@ -340,7 +311,11 @@ void FSingleLumpFont::LoadFON2 (int lump, const uint8_t *data)
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;
@ -396,8 +371,6 @@ void FSingleLumpFont::LoadBMF(int lump, const uint8_t *data)
int numchars, count, totalwidth, nwidth;
int infolen;
int i, chari;
uint8_t raw_palette[256*3];
PalEntry sort_palette[256];
FontType = BMFFONT;
FontHeight = data[5];
@ -439,31 +412,14 @@ void FSingleLumpFont::LoadBMF(int lump, const uint8_t *data)
count = LastChar - FirstChar + 1;
Chars.Resize(count);
// 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)
{
PalEntry *pal = &sort_palette[i];
pal->a = i; // Use alpha part to point back to original entry
pal->r = raw_palette[i*3 + 0];
pal->g = raw_palette[i*3 + 1];
pal->b = raw_palette[i*3 + 2];
int r = (data[17 + i * 3] << 2) | (data[17 + i * 3] >> 4);
int g = (data[18 + i * 3] << 2) | (data[18 + i * 3] >> 4);
int b = (data[19 + i * 3] << 2) | (data[19 + i * 3] >> 4);
Palette[i + 1] = PalEntry(255, r, g, b); // entry 0 (transparent) is not stored in the font file.
}
qsort(sort_palette + 1, ActiveColors - 1, sizeof(PalEntry), BMFCompare);
// 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);
ActiveColors++;
// 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])
@ -510,23 +466,6 @@ void FSingleLumpFont::LoadBMF(int lump, const uint8_t *data)
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
@ -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);
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;
for (i = 0; i < 256; ++i)
for (int i = 0; i < 256; ++i)
{
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].XMove = SpaceWidth;
TexMan.AddGameTexture(Chars[i].TranslatedPic);
@ -567,87 +502,52 @@ void FSingleLumpFont::CheckFON1Chars (double *luminosity)
int8_t code = *data_p++;
if (code >= 0)
{
destSize -= code+1;
destSize -= code + 1;
while (code-- >= 0)
{
used[*data_p++] = 1;
data_p++;
}
}
else if (code != -128)
{
used[*data_p++] = 1;
data_p++;
destSize -= 1 - code;
}
} while (destSize > 0);
}
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;
ActiveColors = 256;
}
//==========================================================================
//
// FSingleLumpFont :: FixupPalette
//
// Finds the best matches for the colors used by a FON2 font and sets up
// some tables like SimpleTranslation.
// Finds the best matches for the colors used by a FON2 font and finds thr
// 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 minlum = 100000000.0;
double diver;
identity[0] = 0;
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 g = palette[1];
int b = palette[2];
int r = palette->r;
int g = palette->g;
int b = palette->b;
double lum = r*0.299 + g*0.587 + b*0.114;
identity[i] = ColorMatcher.Pick(r, g, b);
luminosity[i] = lum;
out_palette[i].r = r;
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;
if (lum > maxlum) maxlum = lum;
if (lum < minlum) minlum = lum;
}
out_palette[0] = 0;
if (rescale)
{
diver = 1.0 / (maxlum - minlum);
}
else
{
diver = 1.0 / 255.0;
}
for (i = 1; i < ActiveColors; ++i)
{
luminosity[i] = (luminosity[i] - minlum) * diver;
}
if (pminlum) *pminlum = int(minlum);
if (pmaxlum) *pmaxlum = int(maxlum);
}
//==========================================================================
@ -661,13 +561,11 @@ void FSingleLumpFont::FixupPalette (uint8_t *identity, double *luminosity, const
void FSingleLumpFont::RecordAllTextureColors(uint32_t* usedcolors)
{
double luminosity[256];
uint8_t identity[256];
PalEntry local_palette[256];
if (FontType == BMFFONT || FontType == FONT2)
{
FixupPalette(identity, luminosity, PaletteData, RescalePalette, local_palette);
FixupPalette(identity, Palette, nullptr, nullptr);
for (int i = 0; i < 256; i++)
{
if (identity[i] != 0) usedcolors[identity[i]]++;

View file

@ -49,8 +49,8 @@
//
//==========================================================================
FFontChar1::FFontChar1 (FImageSource *sourcelump)
: BaseTexture(sourcelump), SourceRemap (nullptr)
FFontChar1::FFontChar1(FImageSource* sourcelump)
: BaseTexture(sourcelump), SourceRemap(nullptr)
{
// now copy all the properties from the base texture
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
// are at the low end of the palette
@ -75,7 +75,7 @@ TArray<uint8_t> FFontChar1::CreatePalettedPixels (int)
if (SourceRemap)
{
for (int x = 0; x < Width*Height; ++x)
for (int x = 0; x < Width * Height; ++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)
: SourceLump (sourcelump), SourcePos (sourcepos), SourceRemap(nullptr)
FFontChar2::FFontChar2(int sourcelump, int sourcepos, int width, int height, int leftofs, int topofs)
: SourceLump(sourcelump), SourcePos(sourcepos)
{
Width = width;
Height = height;
@ -100,17 +100,6 @@ FFontChar2::FFontChar2 (int sourcelump, int sourcepos, int width, int height, in
TopOffset = topofs;
}
//==========================================================================
//
// FFontChar2 :: SetSourceRemap
//
//==========================================================================
void FFontChar2::SetSourceRemap(const uint8_t *sourceremap)
{
SourceRemap = sourceremap;
}
//==========================================================================
//
// FFontChar2 :: Get8BitPixels
@ -121,7 +110,7 @@ void FFontChar2::SetSourceRemap(const uint8_t *sourceremap)
TArray<uint8_t> FFontChar2::CreatePalettedPixels(int)
{
auto lump = fileSystem.OpenFileReader (SourceLump);
auto lump = fileSystem.OpenFileReader(SourceLump);
int destSize = Width * Height;
uint8_t max = 255;
bool rle = true;
@ -129,23 +118,23 @@ TArray<uint8_t> FFontChar2::CreatePalettedPixels(int)
// This is to "fix" bad fonts
{
uint8_t buff[16];
lump.Read (buff, 4);
lump.Read(buff, 4);
if (buff[3] == '2')
{
lump.Read (buff, 7);
lump.Read(buff, 7);
max = buff[6];
lump.Seek (SourcePos - 11, FileReader::SeekCur);
lump.Seek(SourcePos - 11, FileReader::SeekCur);
}
else if (buff[3] == 0x1A)
{
lump.Read(buff, 13);
max = buff[12] - 1;
lump.Seek (SourcePos - 17, FileReader::SeekCur);
lump.Seek(SourcePos - 17, FileReader::SeekCur);
rle = false;
}
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;
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_rew = destSize - 1;
@ -166,11 +155,7 @@ TArray<uint8_t> FFontChar2::CreatePalettedPixels(int)
if (runlen != 0)
{
uint8_t color = lump.ReadUInt8();
color = MIN (color, max);
if (SourceRemap != nullptr)
{
color = SourceRemap[color];
}
color = MIN(color, max);
*dest_p = color;
dest_p += dest_adv;
x--;
@ -194,11 +179,7 @@ TArray<uint8_t> FFontChar2::CreatePalettedPixels(int)
{
uint8_t color = lump.ReadUInt8();
setlen = (-code) + 1;
setval = MIN (color, max);
if (SourceRemap != nullptr)
{
setval = SourceRemap[setval];
}
setval = MIN(color, max);
}
}
}
@ -216,10 +197,6 @@ TArray<uint8_t> FFontChar2::CreatePalettedPixels(int)
{
color = max;
}
if (SourceRemap != nullptr)
{
color = SourceRemap[color];
}
*dest_p = color;
dest_p += dest_adv;
}
@ -230,10 +207,17 @@ TArray<uint8_t> FFontChar2::CreatePalettedPixels(int)
if (destSize < 0)
{
char name[9];
fileSystem.GetFileShortName (name, SourceLump);
fileSystem.GetFileShortName(name, SourceLump);
name[8] = 0;
I_FatalError ("The font %s is corrupt", name);
I_FatalError("The font %s is corrupt", name);
}
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);
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:
int SourceLump;
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++)
{
FStringf buffer("This is font color %d", i);
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, SmallFont, i, 40, 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
}