PrimeWorldEditor/Resource/factory/CFontLoader.cpp

120 lines
3.9 KiB
C++

#include "CFontLoader.h"
#include <Core/Log.h>
#include <iostream>
CFontLoader::CFontLoader()
{
}
CFont* CFontLoader::LoadFont(CInputStream& FONT)
{
// If I seek past a value without reading it, then it's because I don't know what it is
mpFont->mUnknown = FONT.ReadLong();
mpFont->mLineHeight = FONT.ReadLong();
mpFont->mVerticalOffset = FONT.ReadLong();
mpFont->mLineMargin = FONT.ReadLong();
if (mVersion > ePrimeKioskDemo) FONT.Seek(0x4, SEEK_CUR);
FONT.Seek(0x2, SEEK_CUR);
mpFont->mDefaultSize = FONT.ReadLong();
mpFont->mFontName = FONT.ReadString();
if (mVersion <= eEchoes) mpFont->mpFontTexture = (CTexture*) gResCache.GetResource(FONT.ReadLong(), "TXTR");
else mpFont->mpFontTexture = (CTexture*) gResCache.GetResource(FONT.ReadLongLong(), "TXTR");
mpFont->mTextureToken = CToken(mpFont->mpFontTexture);
mpFont->mTextureFormat = FONT.ReadLong();
u32 NumGlyphs = FONT.ReadLong();
mpFont->mGlyphs.reserve(NumGlyphs);
for (u32 iGlyph = 0; iGlyph < NumGlyphs; iGlyph++)
{
CFont::SGlyph Glyph;
Glyph.Character = FONT.ReadShort();
float TexCoordL = FONT.ReadFloat();
float TexCoordU = FONT.ReadFloat();
float TexCoordR = FONT.ReadFloat();
float TexCoordD = FONT.ReadFloat();
Glyph.TexCoords[0] = CVector2f(TexCoordL, TexCoordU); // Upper-left
Glyph.TexCoords[1] = CVector2f(TexCoordR, TexCoordU); // Upper-right
Glyph.TexCoords[2] = CVector2f(TexCoordL, TexCoordD); // Lower-left
Glyph.TexCoords[3] = CVector2f(TexCoordR, TexCoordD); // Lower-right
if (mVersion <= ePrime)
{
Glyph.RGBAChannel = 0;
Glyph.LeftPadding = FONT.ReadLong();
Glyph.PrintAdvance = FONT.ReadLong();
Glyph.RightPadding = FONT.ReadLong();
Glyph.Width = FONT.ReadLong();
Glyph.Height = FONT.ReadLong();
Glyph.BaseOffset = FONT.ReadLong();
Glyph.KerningIndex = FONT.ReadLong();
}
else if (mVersion >= eEchoes)
{
Glyph.RGBAChannel = FONT.ReadByte();
Glyph.LeftPadding = FONT.ReadByte();
Glyph.PrintAdvance = FONT.ReadByte();
Glyph.RightPadding = FONT.ReadByte();
Glyph.Width = FONT.ReadByte();
Glyph.Height = FONT.ReadByte();
Glyph.BaseOffset = FONT.ReadByte();
Glyph.KerningIndex = FONT.ReadShort();
}
mpFont->mGlyphs[Glyph.Character] = Glyph;
}
u32 NumKerningPairs = FONT.ReadLong();
mpFont->mKerningTable.reserve(NumKerningPairs);
for (u32 iKern = 0; iKern < NumKerningPairs; iKern++)
{
CFont::SKerningPair Pair;
Pair.CharacterA = FONT.ReadShort();
Pair.CharacterB = FONT.ReadShort();
Pair.Adjust = FONT.ReadLong();
mpFont->mKerningTable.push_back(Pair);
}
return mpFont;
}
CFont* CFontLoader::LoadFONT(CInputStream& FONT)
{
if (!FONT.IsValid()) return nullptr;
Log::Write("Loading " + FONT.GetSourceString());
CFourCC Magic(FONT);
if (Magic != "FONT")
{
Log::FileError(FONT.GetSourceString(), "Invalid FONT magic: " + StringUtil::ToHexString((u32) Magic.ToLong()));
return nullptr;
}
u32 FileVersion = FONT.ReadLong();
EGame Version = GetFormatVersion(FileVersion);
if (Version == eUnknownVersion)
{
Log::FileError(FONT.GetSourceString(), "Unsupported FONT version: " + StringUtil::ToHexString(FileVersion));
return nullptr;
}
CFontLoader Loader;
Loader.mpFont = new CFont();
Loader.mVersion = Version;
return Loader.LoadFont(FONT);
}
EGame CFontLoader::GetFormatVersion(u32 Version)
{
switch (Version)
{
case 1: return ePrimeKioskDemo;
case 2: return ePrime;
case 4: return eEchoes;
case 5: return eCorruption;
default: return eUnknownVersion;
}
}