- Merged some ECWolf's font code changes. In particular support for retranslating the fonts should the palette change at run time. (This required storing what lump the font was generated from for FON1. This information is stored in FFont since ECWolf also uses the information to allow FONTDEF fonts to be overriden with single lump fonts consistently, but I didn't merge that part as it might break something.)

SVN r3808 (trunk)
This commit is contained in:
Braden Obrzut 2012-08-06 10:25:51 +00:00
parent cb413c600e
commit 70d8daa341
2 changed files with 254 additions and 82 deletions

View file

@ -124,16 +124,26 @@ public:
FSingleLumpFont (const char *fontname, int lump);
protected:
void CheckFON1Chars (int lump, const BYTE *data, double *luminosity);
void CheckFON1Chars (double *luminosity);
void BuildTranslations2 ();
void FixupPalette (BYTE *identity, double *luminosity, const BYTE *palette,
bool rescale, PalEntry *out_palette);
void LoadTranslations ();
void LoadFON1 (int lump, const BYTE *data);
void LoadFON2 (int lump, const BYTE *data);
void LoadBMF (int lump, const BYTE *data);
void CreateFontFromPic (FTextureID picnum);
static int STACK_ARGS BMFCompare(const void *a, const void *b);
enum
{
FONT1,
FONT2,
BMFFONT
} FontType;
BYTE PaletteData[768];
bool RescalePalette;
};
class FSinglePicFont : public FFont
@ -153,16 +163,22 @@ protected:
class FSpecialFont : public FFont
{
public:
FSpecialFont (const char *name, int first, int count, FTexture **lumplist, const bool *notranslate);
FSpecialFont (const char *name, int first, int count, FTexture **lumplist, const bool *notranslate, int lump);
void LoadTranslations();
protected:
bool notranslate[256];
};
// This is a font character that loads a texture and recolors it.
class FFontChar1 : public FTexture
{
public:
FFontChar1 (FTexture *sourcelump, const BYTE *sourceremap);
FFontChar1 (FTexture *sourcelump);
const BYTE *GetColumn (unsigned int column, const Span **spans_out);
const BYTE *GetPixels ();
void SetSourceRemap(const BYTE *sourceremap);
void Unload ();
~FFontChar1 ();
@ -178,11 +194,12 @@ protected:
class FFontChar2 : public FTexture
{
public:
FFontChar2 (int sourcelump, const BYTE *sourceremap, 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);
~FFontChar2 ();
const BYTE *GetColumn (unsigned int column, const Span **spans_out);
const BYTE *GetPixels ();
void SetSourceRemap(const BYTE *sourceremap);
void Unload ();
protected:
@ -322,18 +339,17 @@ FArchive &SerializeFFontPtr (FArchive &arc, FFont* &font)
//
//==========================================================================
FFont::FFont (const char *name, const char *nametemplate, int first, int count, int start)
FFont::FFont (const char *name, const char *nametemplate, int first, int count, int start, int fdlump)
{
int i;
FTextureID lump;
char buffer[12];
FTexture **charlumps;
BYTE usedcolors[256], identity[256];
double *luminosity;
int maxyoffs;
bool doomtemplate = gameinfo.gametype & GAME_DoomChex ? strncmp (nametemplate, "STCFN", 5) == 0 : false;
bool stcfn121 = false;
Lump = fdlump;
Chars = new CharData[count];
charlumps = new FTexture *[count];
PatchRemap = new BYTE[256];
@ -341,7 +357,6 @@ FFont::FFont (const char *name, const char *nametemplate, int first, int count,
LastChar = first + count - 1;
FontHeight = 0;
GlobalKerning = false;
memset (usedcolors, 0, 256);
Name = copystring (name);
Next = FirstFont;
FirstFont = this;
@ -392,18 +407,12 @@ FFont::FFont (const char *name, const char *nametemplate, int first, int count,
{
FontHeight = height;
}
RecordTextureColors (pic, usedcolors);
}
}
}
ActiveColors = SimpleTranslation (usedcolors, PatchRemap, identity, &luminosity);
for (i = 0; i < count; i++)
{
if (charlumps[i] != NULL)
{
Chars[i].Pic = new FFontChar1 (charlumps[i], PatchRemap);
Chars[i].Pic = new FFontChar1 (charlumps[i]);
Chars[i].XMove = Chars[i].Pic->GetScaledWidth();
}
else
@ -424,9 +433,8 @@ FFont::FFont (const char *name, const char *nametemplate, int first, int count,
FixXMoves();
BuildTranslations (luminosity, identity, &TranslationParms[0][0], ActiveColors, NULL);
LoadTranslations();
delete[] luminosity;
delete[] charlumps;
}
@ -803,6 +811,42 @@ int FFont::GetCharWidth (int code) const
return (code < 0) ? SpaceWidth : Chars[code - FirstChar].XMove;
}
//==========================================================================
//
// FFont :: LoadTranslations
//
//==========================================================================
void FFont::LoadTranslations()
{
unsigned int count = LastChar - FirstChar + 1;
BYTE usedcolors[256], identity[256];
double *luminosity;
memset (usedcolors, 0, 256);
for (unsigned int i = 0; i < count; i++)
{
FFontChar1 *pic = static_cast<FFontChar1 *>(Chars[i].Pic);
if(pic)
{
pic->SetSourceRemap(NULL); // Force the FFontChar1 to return the same pixels as the base texture
RecordTextureColors (pic, usedcolors);
}
}
ActiveColors = SimpleTranslation (usedcolors, PatchRemap, identity, &luminosity);
for (unsigned int i = 0; i < count; i++)
{
if(Chars[i].Pic)
static_cast<FFontChar1 *>(Chars[i].Pic)->SetSourceRemap(PatchRemap);
}
BuildTranslations (luminosity, identity, &TranslationParms[0][0], ActiveColors, NULL);
delete[] luminosity;
}
//==========================================================================
//
// FFont :: Preload
@ -854,8 +898,9 @@ void FFont::StaticPreloadFonts()
//
//==========================================================================
FFont::FFont ()
FFont::FFont (int lump)
{
Lump = lump;
Chars = NULL;
PatchRemap = NULL;
Name = NULL;
@ -869,7 +914,7 @@ FFont::FFont ()
//
//==========================================================================
FSingleLumpFont::FSingleLumpFont (const char *name, int lump)
FSingleLumpFont::FSingleLumpFont (const char *name, int lump) : FFont(lump)
{
assert(lump >= 0);
@ -927,6 +972,51 @@ void FSingleLumpFont::CreateFontFromPic (FTextureID picnum)
ActiveColors = 0;
}
//==========================================================================
//
// FSingleLumpFont :: LoadTranslations
//
//==========================================================================
void FSingleLumpFont::LoadTranslations()
{
double luminosity[256];
BYTE identity[256];
PalEntry local_palette[256];
bool useidentity = true;
bool usepalette = false;
const void* ranges;
unsigned int count = LastChar - FirstChar + 1;
switch(FontType)
{
case FONT1:
useidentity = false;
ranges = &TranslationParms[1][0];
CheckFON1Chars (luminosity);
break;
case BMFFONT:
case FONT2:
usepalette = true;
FixupPalette (identity, luminosity, PaletteData, RescalePalette, local_palette);
ranges = &TranslationParms[0][0];
break;
default:
break;
}
for(unsigned int i = 0;i < count;++i)
{
if(Chars[i].Pic)
static_cast<FFontChar2*>(Chars[i].Pic)->SetSourceRemap(PatchRemap);
}
BuildTranslations (luminosity, useidentity ? identity : NULL, ranges, ActiveColors, usepalette ? local_palette : NULL);
}
//==========================================================================
//
// FSingleLumpFont :: LoadFON1
@ -937,7 +1027,6 @@ void FSingleLumpFont::CreateFontFromPic (FTextureID picnum)
void FSingleLumpFont::LoadFON1 (int lump, const BYTE *data)
{
double luminosity[256];
int w, h;
Chars = new CharData[256];
@ -945,6 +1034,7 @@ void FSingleLumpFont::LoadFON1 (int lump, const BYTE *data)
w = data[4] + data[5]*256;
h = data[6] + data[7]*256;
FontType = FONT1;
FontHeight = h;
SpaceWidth = w;
FirstChar = 0;
@ -952,8 +1042,10 @@ void FSingleLumpFont::LoadFON1 (int lump, const BYTE *data)
GlobalKerning = 0;
PatchRemap = new BYTE[256];
CheckFON1Chars (lump, data, luminosity);
BuildTranslations (luminosity, NULL, &TranslationParms[1][0], ActiveColors, NULL);
for(unsigned int i = 0;i < 256;++i)
Chars[i].Pic = NULL;
LoadTranslations();
}
//==========================================================================
@ -969,17 +1061,17 @@ void FSingleLumpFont::LoadFON2 (int lump, const BYTE *data)
{
int count, i, totalwidth;
int *widths2;
BYTE identity[256];
double luminosity[256];
PalEntry local_palette[256];
WORD *widths;
const BYTE *palette;
const BYTE *data_p;
FontType = FONT2;
FontHeight = data[4] + data[5]*256;
FirstChar = data[6];
LastChar = data[7];
ActiveColors = data[10];
PatchRemap = NULL;
RescalePalette = data[9] == 0;
count = LastChar - FirstChar + 1;
Chars = new CharData[count];
@ -1029,7 +1121,7 @@ void FSingleLumpFont::LoadFON2 (int lump, const BYTE *data)
SpaceWidth = totalwidth * 2 / (3 * count);
}
FixupPalette (identity, luminosity, palette, data[9] == 0, local_palette);
memcpy(PaletteData, palette, 768);
data_p = palette + (ActiveColors+1)*3;
@ -1043,7 +1135,7 @@ void FSingleLumpFont::LoadFON2 (int lump, const BYTE *data)
}
else
{
Chars[i].Pic = new FFontChar2 (lump, NULL, int(data_p - data), widths2[i], FontHeight);
Chars[i].Pic = new FFontChar2 (lump, int(data_p - data), widths2[i], FontHeight);
do
{
SBYTE code = *data_p++;
@ -1066,7 +1158,7 @@ void FSingleLumpFont::LoadFON2 (int lump, const BYTE *data)
}
}
BuildTranslations (luminosity, identity, &TranslationParms[0][0], ActiveColors, local_palette);
LoadTranslations();
delete[] widths2;
}
@ -1087,15 +1179,14 @@ void FSingleLumpFont::LoadBMF(int lump, const BYTE *data)
int i, chari;
BYTE raw_palette[256*3];
PalEntry sort_palette[256];
PalEntry local_palette[256];
double luminosity[256];
BYTE identity[256];
FontType = BMFFONT;
FontHeight = data[5];
GlobalKerning = (SBYTE)data[8];
ActiveColors = data[16];
SpaceWidth = -1;
nwidth = -1;
RescalePalette = true;
infolen = data[17 + ActiveColors*3];
chardata = data + 18 + ActiveColors*3 + infolen;
@ -1160,7 +1251,7 @@ void FSingleLumpFont::LoadBMF(int lump, const BYTE *data)
PatchRemap[sort_palette[i].a] = i;
}
FixupPalette(identity, luminosity, raw_palette, true, local_palette);
memcpy(PaletteData, raw_palette, 768);
// 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])
@ -1180,7 +1271,7 @@ void FSingleLumpFont::LoadBMF(int lump, const BYTE *data)
{ // Empty character: skip it.
continue;
}
Chars[chardata[chari] - FirstChar].Pic = new FFontChar2(lump, PatchRemap, int(chardata + chari + 6 - data),
Chars[chardata[chari] - FirstChar].Pic = new FFontChar2(lump, int(chardata + chari + 6 - data),
chardata[chari+1], // width
chardata[chari+2], // height
-(SBYTE)chardata[chari+3], // x offset
@ -1202,7 +1293,7 @@ void FSingleLumpFont::LoadBMF(int lump, const BYTE *data)
}
FixXMoves();
BuildTranslations(luminosity, identity, &TranslationParms[0][0], ActiveColors, local_palette);
LoadTranslations();
}
//==========================================================================
@ -1232,8 +1323,11 @@ int STACK_ARGS FSingleLumpFont::BMFCompare(const void *a, const void *b)
//
//==========================================================================
void FSingleLumpFont::CheckFON1Chars (int lump, const BYTE *data, double *luminosity)
void FSingleLumpFont::CheckFON1Chars (double *luminosity)
{
FMemLump memLump = Wads.ReadLump(Lump);
const BYTE* data = (const BYTE*) memLump.GetMem();
BYTE used[256], reverse[256];
const BYTE *data_p;
int i, j;
@ -1245,8 +1339,11 @@ void FSingleLumpFont::CheckFON1Chars (int lump, const BYTE *data, double *lumino
{
int destSize = SpaceWidth * FontHeight;
Chars[i].Pic = new FFontChar2 (lump, PatchRemap, int(data_p - data), SpaceWidth, FontHeight);
if(!Chars[i].Pic)
{
Chars[i].Pic = new FFontChar2 (Lump, int(data_p - data), SpaceWidth, FontHeight);
Chars[i].XMove = SpaceWidth;
}
// Advance to next char's data and count the used colors.
do
@ -1347,7 +1444,8 @@ void FSingleLumpFont::FixupPalette (BYTE *identity, double *luminosity, const BY
//
//==========================================================================
FSinglePicFont::FSinglePicFont(const char *picname)
FSinglePicFont::FSinglePicFont(const char *picname) :
FFont(-1) // Since lump is only needed for priority information we don't need to worry about this here.
{
FTextureID picnum = TexMan.CheckForTexture (picname, FTexture::TEX_Any);
@ -1413,8 +1511,8 @@ int FSinglePicFont::GetCharWidth (int code) const
//
//==========================================================================
FFontChar1::FFontChar1 (FTexture *sourcelump, const BYTE *sourceremap)
: SourceRemap (sourceremap)
FFontChar1::FFontChar1 (FTexture *sourcelump)
: SourceRemap (NULL)
{
UseType = FTexture::TEX_FontChar;
BaseTexture = sourcelump;
@ -1453,11 +1551,18 @@ void FFontChar1::MakeTexture ()
Pixels = new BYTE[Width*Height];
const BYTE *pix = BaseTexture->GetPixels();
if (!SourceRemap)
{
memcpy(Pixels, pix, Width*Height);
}
else
{
for (int x = 0; x < Width*Height; ++x)
{
Pixels[x] = SourceRemap[pix[x]];
}
}
}
//==========================================================================
//
@ -1476,6 +1581,18 @@ const BYTE *FFontChar1::GetColumn (unsigned int column, const Span **spans_out)
return Pixels + column*Height;
}
//==========================================================================
//
// FFontChar1 :: SetSourceRemap
//
//==========================================================================
void FFontChar1::SetSourceRemap(const BYTE *sourceremap)
{
Unload();
SourceRemap = sourceremap;
}
//==========================================================================
//
// FFontChar1 :: Unload
@ -1510,8 +1627,8 @@ FFontChar1::~FFontChar1 ()
//
//==========================================================================
FFontChar2::FFontChar2 (int sourcelump, const BYTE *sourceremap, int sourcepos, int width, int height, int leftofs, int topofs)
: SourceLump (sourcelump), SourcePos (sourcepos), Pixels (0), Spans (0), SourceRemap(sourceremap)
FFontChar2::FFontChar2 (int sourcelump, int sourcepos, int width, int height, int leftofs, int topofs)
: SourceLump (sourcelump), SourcePos (sourcepos), Pixels (0), Spans (0), SourceRemap(NULL)
{
UseType = TEX_FontChar;
Width = width;
@ -1594,6 +1711,18 @@ const BYTE *FFontChar2::GetColumn (unsigned int column, const Span **spans_out)
return Pixels + column*Height;
}
//==========================================================================
//
// FFontChar2 :: SetSourceRemap
//
//==========================================================================
void FFontChar2::SetSourceRemap(const BYTE *sourceremap)
{
Unload();
SourceRemap = sourceremap;
}
//==========================================================================
//
// FFontChar2 :: MakeTexture
@ -1730,16 +1859,15 @@ void FFontChar2::MakeTexture ()
//
//==========================================================================
FSpecialFont::FSpecialFont (const char *name, int first, int count, FTexture **lumplist, const bool *notranslate)
FSpecialFont::FSpecialFont (const char *name, int first, int count, FTexture **lumplist, const bool *notranslate, int lump) : FFont(lump)
{
int i, j;
FTexture **charlumps;
BYTE usedcolors[256], identity[256];
double *luminosity;
int maxyoffs;
int TotalColors;
FTexture *pic;
memcpy(this->notranslate, notranslate, 256*sizeof(bool));
Name = copystring(name);
Chars = new CharData[count];
charlumps = new FTexture*[count];
@ -1748,7 +1876,6 @@ FSpecialFont::FSpecialFont (const char *name, int first, int count, FTexture **l
LastChar = first + count - 1;
FontHeight = 0;
GlobalKerning = false;
memset (usedcolors, 0, 256);
Next = FirstFont;
FirstFont = this;
@ -1771,7 +1898,58 @@ FSpecialFont::FSpecialFont (const char *name, int first, int count, FTexture **l
{
FontHeight = height;
}
}
if (charlumps[i] != NULL)
{
Chars[i].Pic = new FFontChar1 (charlumps[i]);
Chars[i].XMove = Chars[i].Pic->GetScaledWidth();
}
else
{
Chars[i].Pic = NULL;
Chars[i].XMove = INT_MIN;
}
}
// Special fonts normally don't have all characters so be careful here!
if ('N'-first >= 0 && 'N'-first < count && Chars['N' - first].Pic != NULL)
{
SpaceWidth = (Chars['N' - first].XMove + 1) / 2;
}
else
{
SpaceWidth = 4;
}
FixXMoves();
LoadTranslations();
delete[] charlumps;
}
//==========================================================================
//
// FSpecialFont :: LoadTranslations
//
//==========================================================================
void FSpecialFont::LoadTranslations()
{
int count = LastChar - FirstChar + 1;
BYTE usedcolors[256], identity[256];
double *luminosity;
int TotalColors;
int i, j;
memset (usedcolors, 0, 256);
for (i = 0; i < count; i++)
{
FFontChar1 *pic = static_cast<FFontChar1 *>(Chars[i].Pic);
if(pic)
{
pic->SetSourceRemap(NULL); // Force the FFontChar1 to return the same pixels as the base texture
RecordTextureColors (pic, usedcolors);
}
}
@ -1802,29 +1980,9 @@ FSpecialFont::FSpecialFont (const char *name, int first, int count, FTexture **l
for (i = 0; i < count; i++)
{
if (charlumps[i] != NULL)
{
Chars[i].Pic = new FFontChar1 (charlumps[i], PatchRemap);
Chars[i].XMove = Chars[i].Pic->GetScaledWidth();
if(Chars[i].Pic)
static_cast<FFontChar1 *>(Chars[i].Pic)->SetSourceRemap(PatchRemap);
}
else
{
Chars[i].Pic = NULL;
Chars[i].XMove = INT_MIN;
}
}
// Special fonts normally don't have all characters so be careful here!
if ('N'-first >= 0 && 'N'-first < count && Chars['N' - first].Pic != NULL)
{
SpaceWidth = (Chars['N' - first].XMove + 1) / 2;
}
else
{
SpaceWidth = 4;
}
FixXMoves();
BuildTranslations (luminosity, identity, &TranslationParms[0][0], TotalColors, NULL);
@ -1845,7 +2003,6 @@ FSpecialFont::FSpecialFont (const char *name, int first, int count, FTexture **l
ActiveColors = TotalColors;
delete[] luminosity;
delete[] charlumps;
}
//==========================================================================
@ -1994,7 +2151,7 @@ void V_InitCustomFonts()
}
if (format == 1)
{
FFont *fnt = new FFont (namebuffer, templatebuf, first, count, start);
FFont *fnt = new FFont (namebuffer, templatebuf, first, count, start, llump);
fnt->SetCursor(cursor);
}
else if (format == 2)
@ -2017,7 +2174,7 @@ void V_InitCustomFonts()
}
if (count > 0)
{
FFont *fnt = new FSpecialFont (namebuffer, first, count, &lumplist[first], notranslate);
FFont *fnt = new FSpecialFont (namebuffer, first, count, &lumplist[first], notranslate, llump);
fnt->SetCursor(cursor);
}
}
@ -2396,19 +2553,19 @@ void V_InitFonts()
}
else if (Wads.CheckNumForName ("FONTA_S") >= 0)
{
SmallFont = new FFont ("SmallFont", "FONTA%02u", HU_FONTSTART, HU_FONTSIZE, 1);
SmallFont = new FFont ("SmallFont", "FONTA%02u", HU_FONTSTART, HU_FONTSIZE, 1, -1);
SmallFont->SetCursor('[');
}
else
{
SmallFont = new FFont ("SmallFont", "STCFN%.3d", HU_FONTSTART, HU_FONTSIZE, HU_FONTSTART);
SmallFont = new FFont ("SmallFont", "STCFN%.3d", HU_FONTSTART, HU_FONTSIZE, HU_FONTSTART, -1);
}
}
if (!(SmallFont2 = FFont::FindFont("SmallFont2"))) // Only used by Strife
{
if (Wads.CheckNumForName ("STBFN033", ns_graphics) >= 0)
{
SmallFont2 = new FFont ("SmallFont2", "STBFN%.3d", HU_FONTSTART, HU_FONTSIZE, HU_FONTSTART);
SmallFont2 = new FFont ("SmallFont2", "STBFN%.3d", HU_FONTSTART, HU_FONTSIZE, HU_FONTSTART, -1);
}
else
{
@ -2427,7 +2584,7 @@ void V_InitFonts()
}
else
{
BigFont = new FFont ("BigFont", "FONTB%02u", HU_FONTSTART, HU_FONTSIZE, 1);
BigFont = new FFont ("BigFont", "FONTB%02u", HU_FONTSTART, HU_FONTSIZE, 1, -1);
}
}
if (!(ConFont = FFont::FindFont("ConsoleFont")))
@ -2456,3 +2613,13 @@ void V_ClearFonts()
FFont::FirstFont = NULL;
SmallFont = SmallFont2 = BigFont = ConFont = IntermissionFont = NULL;
}
void V_RetranslateFonts()
{
FFont *font = FFont::FirstFont;
while(font)
{
font->LoadTranslations();
font = font->Next;
}
}

View file

@ -76,15 +76,17 @@ extern int NumTextColors;
class FFont
{
public:
FFont (const char *fontname, const char *nametemplate, int first, int count, int base);
FFont (const char *fontname, const char *nametemplate, int first, int count, int base, int fdlump);
virtual ~FFont ();
virtual FTexture *GetChar (int code, int *const width) const;
virtual int GetCharWidth (int code) const;
FRemapTable *GetColorTranslation (EColorRange range) const;
int GetLump() const { return Lump; }
int GetSpaceWidth () const { return SpaceWidth; }
int GetHeight () const { return FontHeight; }
int GetDefaultKerning () const { return GlobalKerning; }
virtual void LoadTranslations();
void Preload() const;
static FFont *FindFont (const char *fontname);
@ -99,7 +101,7 @@ public:
void SetCursor(char c) { Cursor = c; }
protected:
FFont ();
FFont (int lump);
void BuildTranslations (const double *luminosity, const BYTE *identity,
const void *ranges, int total_colors, const PalEntry *palette);
@ -122,6 +124,7 @@ protected:
TArray<FRemapTable> Ranges;
BYTE *PatchRemap;
int Lump;
char *Name;
FFont *Next;
@ -129,6 +132,7 @@ protected:
friend struct FontsDeleter;
friend void V_ClearFonts();
friend void V_RetranslateFonts();
friend FArchive &SerializeFFontPtr (FArchive &arc, FFont* &font);
};
@ -143,5 +147,6 @@ PalEntry V_LogColorFromColorRange (EColorRange range);
EColorRange V_ParseFontColor (const BYTE *&color_value, int normalcolor, int boldcolor);
FFont *V_GetFont(const char *);
void V_InitFontColors();
void V_RetranslateFonts();
#endif //__V_FONT_H__