I recently dug out some code I experimented with and one of the featues it had were custom multilump fonts (like STCFN***). It didn't take me long to port it to ZDoom's font management system and here's the result:
Code: Select all
//===========================================================================
//
// Essentially a normal multilump font but
// with an explicit list of character patches
//
//===========================================================================
class FSpecialFont : public FFont
{
public:
FSpecialFont (const char *name, int first, int count, int * lumplist, const bool * notranslate);
};
FSpecialFont::FSpecialFont (const char *name, int first, int count, int * lumplist, const bool * notranslate)
{
int i, j, lump;
char buffer[12];
int *charlumps;
byte usedcolors[256], identity[256];
double *luminosity;
int maxyoffs;
int TotalColors;
Name=copystring(name);
Chars = new CharData[count];
charlumps = new int[count];
PatchRemap = new BYTE[256];
Ranges = NULL;
FirstChar = first;
LastChar = first + count - 1;
FontHeight = 0;
GlobalKerning = false;
memset (usedcolors, 0, 256);
Name = copystring (name);
Next = FirstFont;
FirstFont = this;
maxyoffs = 0;
for (i = 0; i < count; i++)
{
lump = charlumps[i] = lumplist[i];
if (lump >= 0)
{
Wads.GetLumpName(buffer,lump);
FTexture *pic = TexMan[TexMan.AddPatch (buffer)];
int height = pic->GetHeight();
int yoffs = pic->TopOffset;
if (yoffs > maxyoffs)
{
maxyoffs = yoffs;
}
height += abs (yoffs);
if (height > FontHeight)
{
FontHeight = height;
}
/* experimental True Color OpenGL font support ;)
if (TexMan.GLSupport())
{
RecordGLTextureColors(lump, usedcolors);
}
else
*/
{
RecordTextureColors (pic, usedcolors);
}
}
}
// exclude the non-translated colors from the translation calculation
if (notranslate!=NULL)
{
for(i=0;i<256;i++) if (notranslate[i]) usedcolors[i]=false;
}
TotalColors = ActiveColors = SimpleTranslation (usedcolors, PatchRemap, identity, &luminosity);
// Map all untranslated colors into the table of used colors
if (notranslate!=NULL)
{
for(i=0;i<256;i++)
{
if (notranslate[i])
{
PatchRemap[i]=TotalColors;
identity[TotalColors]=i;
TotalColors++;
}
}
}
for (i = 0; i < count; i++)
{
if (charlumps[i] >= 0)
{
/* experimental True Color OpenGL font support ;)
if (TexMan.GLSupport())
{
Chars[i].Pic = new FGLFontChar1(charlumps[i], PatchRemap, TotalColors, &Ranges);
}
else
*/
{
Chars[i].Pic = new FFontChar1 (charlumps[i], PatchRemap);
}
}
else
{
Chars[i].Pic = NULL;
}
}
// Special fonts normally don't have all characters so be careful here!
if ('N'-first>=0 && 'N'-first<count && Chars['N' - first].Pic)
{
SpaceWidth = (Chars['N' - first].Pic->GetWidth() + 1) / 2;
}
else SpaceWidth=4;
BuildTranslations (luminosity, identity/*, TexMan.GLSupport()*/);
// add the untranslated colors to the Ranges table
if (ActiveColors<TotalColors)
{
int factor = 1;//3 * TexMan.GLSupport();
byte * oldranges=Ranges;
Ranges = new byte[NUM_TEXT_COLORS * TotalColors * factor ];
for (i = 0; i < CR_UNTRANSLATED; i++)
{
memcpy(&Ranges[i * TotalColors * factor], &oldranges[i * ActiveColors * factor], ActiveColors * factor);
for(j=ActiveColors;j<TotalColors;j++)
{
/* experimental True Color OpenGL font support ;)
if (TexMan.GLSupport())
{
Ranges[(TotalColors*i + j)*3 + 0]=GPalette.BaseColors[identity[j]].r;
Ranges[(TotalColors*i + j)*3 + 1]=GPalette.BaseColors[identity[j]].g;
Ranges[(TotalColors*i + j)*3 + 2]=GPalette.BaseColors[identity[j]].b;
}
else
*/
{
Ranges[TotalColors*i + j]=identity[j];
}
}
}
delete [] oldranges;
}
ActiveColors=TotalColors;
delete[] luminosity;
delete[] charlumps;
}
//===========================================================================
//
// Initialize a list of custom multipatch fonts
//
//===========================================================================
BOOL SC_CheckNumber (void);
void V_InitCustomFonts()
{
int lumplist[256];
bool notranslate[256];
char namebuffer[16],templatebuf[16];
int adder=0;
int i;
int llump,lastlump=-1;
int format=0;
int start=33;
int first=33;
int count=223;
while ((llump = Wads.FindLump ("FONTDEFS", &lastlump)) != -1)
{
SC_OpenLumpNum(llump,"FONTDEFS");
while (SC_GetString())
{
memset(lumplist,-1,sizeof(lumplist));
memset(notranslate,0,sizeof(notranslate));
strncpy(namebuffer,sc_String,16);
namebuffer[15]=0;
format=0;
start=33;
first=33;
count=223;
SC_MustGetStringName("{");
while (!SC_CheckString("}"))
{
SC_MustGetString();
if (SC_Compare("TEMPLATE"))
{
if (format==2) goto wrong;
SC_MustGetString();
strncpy(templatebuf,sc_String,16);
templatebuf[15]=0;
format=1;
}
else if (SC_Compare("BASE"))
{
if (format==2) goto wrong;
SC_MustGetNumber();
start=sc_Number;
format=1;
}
else if (SC_Compare("FIRST"))
{
if (format==2) goto wrong;
SC_MustGetNumber();
first=sc_Number;
format=1;
}
else if (SC_Compare("COUNT"))
{
if (format==2) goto wrong;
SC_MustGetNumber();
count=sc_Number;
format=1;
}
else if (SC_Compare("NOTRANSLATION"))
{
if (format==1) goto wrong;
while (SC_CheckNumber() && !sc_Crossed)
{
if (sc_Number>=0 && sc_Number<256) notranslate[sc_Number]=true;
}
format=2;
}
else
{
if (format==1) goto wrong;
int * p=&lumplist[*(unsigned char*)sc_String];
SC_MustGetString();
*p=Wads.CheckNumForName(sc_String);
format=2;
}
}
if (format==1)
{
new FFont(namebuffer, templatebuf, first, count, start);
}
else if (format==2)
{
for(i=0;i<256;i++)
{
if (lumplist[i]!=-1)
{
first=i;
break;
}
}
for(i=255;i>=0;i--)
{
if (lumplist[i]!=-1)
{
count=i-first+1;
break;
}
}
if (count>0) new FSpecialFont(namebuffer, first, count, &lumplist[first], notranslate);
}
else goto wrong;
}
SC_Close();
}
return;
wrong:
SC_ScriptError("Invalid combination of properties in font '%s'", namebuffer);
}
Just copy and paste it to the end of V_Font.cpp, change the line
Code: Select all
SpaceWidth = (Chars['N' - first].Pic->GetWidth() + 1) / 2;
Code: Select all
if ('N'-first>=0 && 'N'-first<count && Chars['N' - first].Pic)
{
SpaceWidth = (Chars['N' - first].Pic->GetWidth() + 1) / 2;
}
else SpaceWidth=4;
and call V_InitCustomFonts from V_Init and it should work.
And here's a small WAD that demonstrates it.