- made some changes to the font and texture system to allow late loading of the palette.

The base palette can be set via .def files so that the engine has no access to it until the entire game state is set up.
This means that font translations and PNG palette remap tables cannot be built when the owning objects are created.
For PNGs this has the added advantage that they only get done when really required and not unconditionally - most of the time the remap table isn't even needed here.

Thid fixes the slider graphics in the option menus.

# Conflicts:
#	source/core/gamecontrol.cpp

# Conflicts:
#	source/core/gamecontrol.cpp
This commit is contained in:
Christoph Oelckers 2020-05-01 13:13:46 +02:00
parent b233cc2ea5
commit 7109ce4e30
9 changed files with 137 additions and 71 deletions

View file

@ -120,7 +120,7 @@ void scrLoadPalette(void)
ThrowError("TRANS.TLU not found");
paletteloaded |= PALETTE_TRANSLUC;
palettePostLoadTables();
enginePostInit();
}

View file

@ -2125,6 +2125,7 @@ int32_t enginePostInit(void)
if (!(paletteloaded & PALETTE_TRANSLUC))
I_FatalError("No translucency table found.");
V_LoadTranslations(); // loading the translations must be delayed until the palettes have been fully set up.
palettePostLoadTables();
TileFiles.SetupReverseTileMap();
return 0;

View file

@ -372,10 +372,6 @@ FFont::FFont (const char *name, const char *nametemplate, const char *filetempla
FixXMoves();
}
if (!noTranslate) LoadTranslations();
}
void FFont::ReadSheetFont(TArray<FolderEntry> &folderdata, int width, int height, const DVector2 &Scale)
@ -443,16 +439,13 @@ void FFont::ReadSheetFont(TArray<FolderEntry> &folderdata, int width, int height
if (lump != nullptr)
{
auto pic = (*lump)->GetTexture();
auto b = pic->Get8BitPixels(false);
Chars[i].OriginalPic = MakeGameTexture(pic, nullptr, ETextureType::FontChar);
Chars[i].OriginalPic = (*lump)->GetUseType() == ETextureType::FontChar? (*lump) : MakeGameTexture(pic, nullptr, ETextureType::FontChar);
Chars[i].OriginalPic->SetUseType(ETextureType::FontChar);
Chars[i].OriginalPic->CopySize(*lump);
Chars[i].TranslatedPic = MakeGameTexture(new FImageTexture(new FFontChar1(pic->GetImage())), nullptr, ETextureType::FontChar);
Chars[i].TranslatedPic->CopySize(*lump);
Chars[i].TranslatedPic->SetUseType(ETextureType::FontChar);
TexMan.AddGameTexture(Chars[i].OriginalPic);
if (Chars[i].OriginalPic != *lump) TexMan.AddGameTexture(Chars[i].OriginalPic);
TexMan.AddGameTexture(Chars[i].TranslatedPic);
}
Chars[i].XMove = width;

View file

@ -245,6 +245,7 @@ public:
FHexFont (const char *fontname, int lump)
: FFont(lump)
{
const int spacing = 9;
assert(lump >= 0);
FontName = fontname;
@ -258,8 +259,22 @@ public:
SpaceWidth = 9;
GlobalKerning = 0;
translateUntranslated = true;
LoadTranslations();
Chars.Resize(LastChar - FirstChar + 1);
for (int i = FirstChar; i <= LastChar; i++)
{
if (hexdata.glyphmap[i] > 0)
{
auto offset = hexdata.glyphmap[i];
int size = hexdata.glyphdata[offset] / 16;
Chars[i - FirstChar].TranslatedPic = MakeGameTexture(new FImageTexture(new FHexFontChar(&hexdata.glyphdata[offset + 1], size, size * 9, 16)), nullptr, ETextureType::FontChar);
Chars[i - FirstChar].OriginalPic = Chars[i - FirstChar].TranslatedPic;
Chars[i - FirstChar].XMove = size * spacing;
TexMan.AddGameTexture(Chars[i - FirstChar].TranslatedPic);
}
else Chars[i - FirstChar].XMove = spacing;
}
}
//==========================================================================
@ -270,7 +285,6 @@ public:
void LoadTranslations()
{
const int spacing = 9;
double luminosity[256];
memset (PatchRemap, 0, 256);
@ -282,20 +296,6 @@ public:
}
ActiveColors = 18;
Chars.Resize(LastChar - FirstChar + 1);
for (int i = FirstChar; i <= LastChar; i++)
{
if (hexdata.glyphmap[i] > 0)
{
auto offset = hexdata.glyphmap[i];
int size = hexdata.glyphdata[offset] / 16;
Chars[i - FirstChar].TranslatedPic = MakeGameTexture(new FImageTexture(new FHexFontChar (&hexdata.glyphdata[offset+1], size, size * 9, 16)), nullptr, ETextureType::FontChar);
Chars[i - FirstChar].XMove = size * spacing;
TexMan.AddGameTexture(Chars[i - FirstChar].TranslatedPic);
}
else Chars[i - FirstChar].XMove = spacing;
}
BuildTranslations (luminosity, nullptr, &TranslationParms[1][0], ActiveColors, nullptr);
}
@ -317,6 +317,7 @@ public:
FHexFont2(const char *fontname, int lump)
: FFont(lump)
{
const int spacing = 9;
assert(lump >= 0);
FontName = fontname;
@ -330,8 +331,21 @@ public:
SpaceWidth = 9;
GlobalKerning = -1;
translateUntranslated = true;
Chars.Resize(LastChar - FirstChar + 1);
for (int i = FirstChar; i <= LastChar; i++)
{
if (hexdata.glyphmap[i] > 0)
{
auto offset = hexdata.glyphmap[i];
int size = hexdata.glyphdata[offset] / 16;
Chars[i - FirstChar].TranslatedPic = MakeGameTexture(new FImageTexture(new FHexFontChar2(&hexdata.glyphdata[offset + 1], size, 2 + size * 8, 18)), nullptr, ETextureType::FontChar);
Chars[i - FirstChar].OriginalPic = Chars[i - FirstChar].TranslatedPic;
Chars[i - FirstChar].XMove = size * spacing;
TexMan.AddGameTexture(Chars[i - FirstChar].TranslatedPic);
}
else Chars[i - FirstChar].XMove = spacing;
LoadTranslations();
}
}
//==========================================================================
@ -342,7 +356,6 @@ public:
void LoadTranslations() override
{
const int spacing = 9;
double luminosity[256];
memset(PatchRemap, 0, 256);
@ -354,20 +367,6 @@ public:
}
ActiveColors = 18;
Chars.Resize(LastChar - FirstChar + 1);
for (int i = FirstChar; i <= LastChar; i++)
{
if (hexdata.glyphmap[i] > 0)
{
auto offset = hexdata.glyphmap[i];
int size = hexdata.glyphdata[offset] / 16;
Chars[i - FirstChar].TranslatedPic = MakeGameTexture(new FImageTexture(new FHexFontChar2(&hexdata.glyphdata[offset + 1], size, 2 + size * 8, 18)), nullptr, ETextureType::FontChar);
Chars[i - FirstChar].XMove = size * spacing;
TexMan.AddGameTexture(Chars[i - FirstChar].TranslatedPic);
}
else Chars[i - FirstChar].XMove = spacing;
}
BuildTranslations(luminosity, nullptr, &TranslationParms[0][0], ActiveColors, nullptr);
}

View file

@ -176,6 +176,7 @@ void FSingleLumpFont::CreateFontFromPic (FTextureID picnum)
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;
@ -255,7 +256,6 @@ void FSingleLumpFont::LoadFON1 (int lump, const uint8_t *data)
LastChar = 255; // This is to allow LoadTranslations to function. The way this is all set up really needs to be changed.
GlobalKerning = 0;
translateUntranslated = true;
LoadTranslations();
LastChar = 0x2122;
// Move the Windows-1252 characters to their proper place.
@ -350,10 +350,12 @@ void FSingleLumpFont::LoadFON2 (int lump, const uint8_t *data)
if (destSize <= 0)
{
Chars[i].TranslatedPic = nullptr;
Chars[i].OriginalPic = nullptr;
}
else
{
Chars[i].TranslatedPic = MakeGameTexture(new FImageTexture(new FFontChar2 (lump, int(data_p - data), widths2[i], FontHeight)), nullptr, ETextureType::FontChar);
Chars[i].OriginalPic = Chars[i].TranslatedPic;
TexMan.AddGameTexture(Chars[i].TranslatedPic);
do
{
@ -376,8 +378,6 @@ void FSingleLumpFont::LoadFON2 (int lump, const uint8_t *data)
I_Error ("Overflow decompressing char %d (%c) of %s", i, i, FontName.GetChars());
}
}
LoadTranslations();
}
//==========================================================================
@ -489,6 +489,7 @@ void FSingleLumpFont::LoadBMF(int lump, const uint8_t *data)
-(int8_t)chardata[chari+4] // y offset
)), nullptr, ETextureType::FontChar);
Chars[chardata[chari] - FirstChar].TranslatedPic = tex;
Chars[chardata[chari] - FirstChar].OriginalPic = tex;
TexMan.AddGameTexture(tex);
}
@ -506,7 +507,6 @@ void FSingleLumpFont::LoadBMF(int lump, const uint8_t *data)
}
FixXMoves();
LoadTranslations();
}
//==========================================================================
@ -555,6 +555,7 @@ void FSingleLumpFont::CheckFON1Chars (double *luminosity)
if(!Chars[i].TranslatedPic)
{
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);
}

View file

@ -140,10 +140,6 @@ FSpecialFont::FSpecialFont (const char *name, int first, int count, FGameTexture
{
ActiveColors = 0;
}
else
{
LoadTranslations();
}
}
//==========================================================================

View file

@ -828,6 +828,14 @@ void V_InitFonts()
AlternativeSmallFont = OriginalSmallFont;
}
void V_LoadTranslations()
{
for (auto font = FFont::FirstFont; font; font = font->Next)
{
if (!font->noTranslate) font->LoadTranslations();
}
}
void V_ClearFonts()
{
while (FFont::FirstFont != nullptr)

View file

@ -81,6 +81,7 @@ using GlyphSet = TMap<int, FGameTexture*>;
class FFont
{
friend void V_LoadTranslations();
public:
enum EFontType
@ -192,5 +193,6 @@ 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_LoadTranslations();

View file

@ -60,6 +60,7 @@ public:
protected:
void ReadAlphaRemap(FileReader *lump, uint8_t *alpharemap);
void SetupPalette(FileReader &lump);
uint8_t BitDepth;
uint8_t ColorType;
@ -153,11 +154,6 @@ FPNGTexture::FPNGTexture (FileReader &lump, int lumpnum, int width, int height,
: FImageSource(lumpnum),
BitDepth(depth), ColorType(colortype), Interlace(interlace), HaveTrans(false)
{
union
{
uint32_t palette[256];
uint8_t pngpal[256][3];
} p;
uint8_t trans[256];
uint32_t len, id;
int i;
@ -211,15 +207,7 @@ FPNGTexture::FPNGTexture (FileReader &lump, int lumpnum, int width, int height,
case MAKE_ID('P','L','T','E'):
PaletteSize = MIN<int> (len / 3, 256);
StartOfPalette = (uint32_t)lump.Tell();
lump.Read (p.pngpal, PaletteSize * 3);
if (PaletteSize * 3 != (int)len)
{
lump.Seek (len - PaletteSize * 3, FileReader::SeekCur);
}
for (i = PaletteSize - 1; i >= 0; --i)
{
p.palette[i] = MAKERGB(p.pngpal[i][0], p.pngpal[i][1], p.pngpal[i][2]);
}
lump.Seek(len, FileReader::SeekCur);
break;
case MAKE_ID('t','R','N','S'):
@ -249,9 +237,6 @@ FPNGTexture::FPNGTexture (FileReader &lump, int lumpnum, int width, int height,
{
bMasked = true;
PaletteSize = 256;
PaletteMap = (uint8_t*)ImageArena.Alloc(PaletteSize);
memcpy (PaletteMap, GPalette.GrayMap, 256);
PaletteMap[NonPaletteTrans[0]] = 0;
}
else
{
@ -260,14 +245,11 @@ FPNGTexture::FPNGTexture (FileReader &lump, int lumpnum, int width, int height,
break;
case 3: // Paletted
PaletteMap = (uint8_t*)ImageArena.Alloc(PaletteSize);
MakeRemap ((uint32_t*)GPalette.BaseColors, p.palette, PaletteMap, trans, PaletteSize);
for (i = 0; i < PaletteSize; ++i)
{
if (trans[i] == 0)
{
bMasked = true;
PaletteMap[i] = 0;
}
}
break;
@ -282,6 +264,87 @@ FPNGTexture::FPNGTexture (FileReader &lump, int lumpnum, int width, int height,
}
}
void FPNGTexture::SetupPalette(FileReader &lump)
{
union
{
uint32_t palette[256];
uint8_t pngpal[256][3];
} p;
uint8_t trans[256];
uint32_t len, id;
int i;
auto pos = lump.Tell();
memset(trans, 255, 256);
// Parse pre-IDAT chunks. I skip the CRCs. Is that bad?
lump.Seek(33, FileReader::SeekSet);
lump.Read(&len, 4);
lump.Read(&id, 4);
while (id != MAKE_ID('I', 'D', 'A', 'T') && id != MAKE_ID('I', 'E', 'N', 'D'))
{
len = BigLong((unsigned int)len);
switch (id)
{
default:
lump.Seek(len, FileReader::SeekCur);
break;
case MAKE_ID('P', 'L', 'T', 'E'):
lump.Read(p.pngpal, PaletteSize * 3);
if (PaletteSize * 3 != (int)len)
{
lump.Seek(len - PaletteSize * 3, FileReader::SeekCur);
}
for (i = PaletteSize - 1; i >= 0; --i)
{
p.palette[i] = MAKERGB(p.pngpal[i][0], p.pngpal[i][1], p.pngpal[i][2]);
}
break;
case MAKE_ID('t', 'R', 'N', 'S'):
lump.Read(trans, len);
break;
}
lump.Seek(4, FileReader::SeekCur); // Skip CRC
lump.Read(&len, 4);
id = MAKE_ID('I', 'E', 'N', 'D');
lump.Read(&id, 4);
}
StartOfIDAT = (uint32_t)lump.Tell() - 8;
switch (ColorType)
{
case 0: // Grayscale
if (HaveTrans && NonPaletteTrans[0] < 256)
{
PaletteMap = (uint8_t*)ImageArena.Alloc(PaletteSize);
memcpy(PaletteMap, GPalette.GrayMap, 256);
PaletteMap[NonPaletteTrans[0]] = 0;
}
break;
case 3: // Paletted
PaletteMap = (uint8_t*)ImageArena.Alloc(PaletteSize);
MakeRemap((uint32_t*)GPalette.BaseColors, p.palette, PaletteMap, trans, PaletteSize);
for (i = 0; i < PaletteSize; ++i)
{
if (trans[i] == 0)
{
PaletteMap[i] = 0;
}
}
break;
default:
break;
}
lump.Seek(pos, FileReader::SeekSet);
}
//==========================================================================
//
//
@ -337,6 +400,7 @@ TArray<uint8_t> FPNGTexture::CreatePalettedPixels(int conversion)
{
if (conversion != luminance)
{
if (!PaletteMap) SetupPalette(lfr);
ImageHelpers::FlipSquareBlockRemap (Pixels.Data(), Width, PaletteMap);
}
else if (ColorType == 0)
@ -355,6 +419,7 @@ TArray<uint8_t> FPNGTexture::CreatePalettedPixels(int conversion)
TArray<uint8_t> newpix(Width*Height, true);
if (conversion != luminance)
{
if (!PaletteMap) SetupPalette(lfr);
ImageHelpers::FlipNonSquareBlockRemap (newpix.Data(), Pixels.Data(), Width, Height, Width, PaletteMap);
}
else if (ColorType == 0)
@ -409,6 +474,7 @@ TArray<uint8_t> FPNGTexture::CreatePalettedPixels(int conversion)
case 4: // Grayscale + Alpha
pitch = Width * 2;
backstep = Height * pitch - 2;
if (!PaletteMap) SetupPalette(lfr);
for (x = Width; x > 0; --x)
{
for (y = Height; y > 0; --y)