- cleanup of font init to have less special cases

To make things easier, DBIGFONT, SBIGFONT and HBIGFONT will now be renamed in the lump directory to make things a bit easier to handle.

Another change is to make font folders atomic units to prevent cross-pollution between incompatible fonts. The only exception to this are the def* folders because they need to piece together their fonts from both zd_extra.pk3 and the IWADs.
This commit is contained in:
Christoph Oelckers 2019-02-12 00:19:44 +01:00
parent fe981c68d3
commit 0b8fb3ac1a
8 changed files with 66 additions and 41 deletions

View file

@ -51,7 +51,7 @@
#include "events.h"
#include "i_system.h"
TArray<cluster_info_t> wadclusterinfos;
static TArray<cluster_info_t> wadclusterinfos;
TArray<level_info_t> wadlevelinfos;
level_info_t TheDefaultLevelInfo;

View file

@ -759,6 +759,7 @@ void FWadCollection::RenameSprites ()
{
bool renameAll;
bool MNTRZfound = false;
const char *altbigfont = gameinfo.gametype == GAME_Strife? "SBIGFONT" : (gameinfo.gametype & GAME_Raven)? "HBIGFONT" : "DBIGFONT";
static const uint32_t HereticRenames[] =
{ MAKE_ID('H','E','A','D'), MAKE_ID('L','I','C','H'), // Ironlich
@ -889,6 +890,11 @@ void FWadCollection::RenameSprites ()
}
}
}
else if (LumpInfo[i].lump->Namespace == ns_global)
{
// Rename the game specific big font lumps so that the font manager does not have to do problematic special checks for them.
if (!strcmp(LumpInfo[i].lump->Name, altbigfont)) strcpy(LumpInfo[i].lump->Name, "BIGFONT");
}
}
}
@ -1265,6 +1271,8 @@ FResourceLump *FWadCollection::GetLumpRecord(int lump) const
// GetLumpsInFolder
//
// Gets all lumps within a single folder in the hierarchy.
// If 'atomic' is set, it treats folders as atomic, i.e. only the
// content of the last found resource file having the given folder name gets used.
//
//==========================================================================
@ -1275,7 +1283,7 @@ static int folderentrycmp(const void *a, const void *b)
return strcmp(A->name, B->name);
}
unsigned FWadCollection::GetLumpsInFolder(const char *inpath, TArray<FolderEntry> &result) const
unsigned FWadCollection::GetLumpsInFolder(const char *inpath, TArray<FolderEntry> &result, bool atomic) const
{
FString path = inpath;
FixPathSeperator(path);
@ -1287,13 +1295,31 @@ unsigned FWadCollection::GetLumpsInFolder(const char *inpath, TArray<FolderEntry
if (LumpInfo[i].lump->FullName.IndexOf(path) == 0)
{
// Only if it hasn't been replaced.
if (Wads.CheckNumForFullName(LumpInfo[i].lump->FullName) == i)
if ((unsigned)Wads.CheckNumForFullName(LumpInfo[i].lump->FullName) == i)
{
result.Push({ LumpInfo[i].lump->FullName.GetChars(), i });
}
}
}
if (result.Size())
{
int maxfile = -1;
if (atomic)
{
// Find the highest resource file having content in the given folder.
for (auto & entry : result)
{
int thisfile = Wads.GetLumpFile(entry.lumpnum);
if (thisfile > maxfile) maxfile = thisfile;
}
// Delete everything from older files.
for (int i = result.Size() - 1; i >= 0; i--)
{
if ((int)result[i].lumpnum != maxfile) result.Delete(i);
}
}
qsort(result.Data(), result.Size(), sizeof(FolderEntry), folderentrycmp);
}
return result.Size();
}

View file

@ -179,7 +179,7 @@ public:
int GetLumpIndexNum (int lump) const; // Returns the RFF index number for this lump
FResourceLump *GetLumpRecord(int lump) const; // Returns the FResourceLump, in case the caller wants to have direct access to the lump cache.
bool CheckLumpName (int lump, const char *name) const; // [RH] Returns true if the names match
unsigned GetLumpsInFolder(const char *path, TArray<FolderEntry> &result) const;
unsigned GetLumpsInFolder(const char *path, TArray<FolderEntry> &result, bool atomic) const;
bool IsEncryptedFile(int lump) const;

View file

@ -404,7 +404,7 @@ static void ParseListMenuBody(FScanner &sc, DListMenuDescriptor *desc)
}
else if (args[i] == TypeFont)
{
auto f = FFont::FindFont(sc.String);
auto f = V_GetFont(sc.String);
if (f == nullptr)
{
sc.ScriptError("Unknown font %s", sc.String);

View file

@ -955,7 +955,7 @@ static int stripaccent(int code)
return code;
}
FFont *V_GetFont(const char *name)
FFont *V_GetFont(const char *name, const char *fontlumpname)
{
FFont *font = FFont::FindFont (name);
if (font == nullptr)
@ -967,14 +967,14 @@ FFont *V_GetFont(const char *name)
FStringf path("fonts/%s/", name);
// Use a folder-based font only if it comes from a later file than the single lump version.
if (Wads.GetLumpsInFolder(path, folderdata))
if (Wads.GetLumpsInFolder(path, folderdata, true))
{
// This assumes that any custom font comes in one piece and not distributed across multiple resource files.
folderfile = Wads.GetLumpFile(folderdata[0].lumpnum);
}
lump = Wads.CheckNumForFullName(name, true);
lump = Wads.CheckNumForFullName(fontlumpname? fontlumpname : name, true);
if (lump != -1 && Wads.GetLumpFile(lump) >= folderfile)
{
@ -1003,7 +1003,7 @@ FFont *V_GetFont(const char *name)
return new FFont(name, nullptr, path, HU_FONTSTART, HU_FONTSIZE, 1, -1);
}
}
return nullptr;
return font;
}
//==========================================================================
@ -1073,7 +1073,9 @@ FFont::FFont (const char *name, const char *nametemplate, const char *filetempla
{
TArray<FolderEntry> folderdata;
FStringf path("fonts/%s/", filetemplate);
if (Wads.GetLumpsInFolder(path, folderdata))
// If a name template is given, collect data from all resource files.
// For anything else, each folder is being treated as an atomic, self-contained unit and mixing from different glyph sets is blocked.
if (Wads.GetLumpsInFolder(path, folderdata, nametemplate == nullptr))
{
// all valid lumps must be named with a hex number that represents its Unicode character index.
for (auto &entry : folderdata)
@ -2962,20 +2964,14 @@ void V_InitFonts()
V_InitCustomFonts ();
// load the heads-up font
if (!(SmallFont = V_GetFont("SmallFont")))
if (!(SmallFont = V_GetFont("SmallFont", "SMALLFNT")))
{
int i;
if ((i = Wads.CheckNumForName("SMALLFNT")) >= 0)
{
SmallFont = new FSingleLumpFont("SmallFont", i);
}
else if (Wads.CheckNumForName ("FONTA_S") >= 0)
if (Wads.CheckNumForName ("FONTA_S") >= 0)
{
SmallFont = new FFont ("SmallFont", "FONTA%02u", "defsmallfont", HU_FONTSTART, HU_FONTSIZE, 1, -1);
SmallFont->SetCursor('[');
}
else
else if (Wads.CheckNumForName ("STCFN033", ns_graphics) >= 0)
{
SmallFont = new FFont ("SmallFont", "STCFN%.3d", "defsmallfont", HU_FONTSTART, HU_FONTSIZE, HU_FONTSTART, -1);
}
@ -2986,33 +2982,17 @@ void V_InitFonts()
{
SmallFont2 = new FFont ("SmallFont2", "STBFN%.3d", "defsmallfont2", HU_FONTSTART, HU_FONTSIZE, HU_FONTSTART, -1);
}
else
{
SmallFont2 = SmallFont;
}
}
if (!(BigFont = V_GetFont("BigFont")))
{
const char *bigfontname = (gameinfo.gametype & GAME_DoomChex)? "DBIGFONT" : (gameinfo.gametype == GAME_Strife)? "SBIGFONT" : "HBIGFONT";
try
if (gameinfo.gametype & GAME_Raven)
{
BigFont = new FSingleLumpFont ("BigFont", Wads.CheckNumForName(bigfontname));
}
catch (CRecoverableError &err)
{
BigFont = new FFont ("BigFont", (gameinfo.gametype & GAME_Raven)? "FONTB%02u" : nullptr, "defbigfont", HU_FONTSTART, HU_FONTSIZE, 1, -1);
BigFont = new FFont ("BigFont", "FONTB%02u", "defbigfont", HU_FONTSTART, HU_FONTSIZE, 1, -1);
}
}
if (!(ConFont = V_GetFont("ConsoleFont")))
if (!(ConFont = V_GetFont("ConsoleFont", "CONFONT")))
{
try
{
ConFont = new FSingleLumpFont ("ConsoleFont", Wads.GetNumForName ("CONFONT"));
}
catch (CRecoverableError &err)
{
ConFont = new FFont ("ConsoleFont", nullptr, "defbigfont", HU_FONTSTART, HU_FONTSIZE, 1, -1);
}
ConFont = SmallFont;
}
if (!(IntermissionFont = FFont::FindFont("IntermissionFont")))
{
@ -3025,6 +3005,25 @@ void V_InitFonts()
IntermissionFont = BigFont;
}
}
// This can only happen if gzdoom.pk3 is corrupted. ConFont should always be present.
if (ConFont == nullptr)
{
I_FatalError("Console font not found.");
}
// SmallFont and SmallFont2 have no default provided by the engine. BigFont only has in non-Raven games.
if (SmallFont == nullptr)
{
SmallFont = ConFont;
}
if (SmallFont2 == nullptr)
{
SmallFont2 = SmallFont;
}
if (BigFont == nullptr)
{
BigFont = SmallFont;
}
}
void V_ClearFonts()

View file

@ -150,7 +150,7 @@ void V_ClearFonts();
EColorRange V_FindFontColor (FName name);
PalEntry V_LogColorFromColorRange (EColorRange range);
EColorRange V_ParseFontColor (const uint8_t *&color_value, int normalcolor, int boldcolor);
FFont *V_GetFont(const char *);
FFont *V_GetFont(const char *fontname, const char *fontlumpname = nullptr);
void V_InitFontColors();
#endif //__V_FONT_H__

Binary file not shown.