ttf字体文件中的所有数据都是用的大端模式存储
解析ttf字体文件用到的结构体
CTTFFontOffsetTable
class CTTFFontOffsetTable
{
public:
CTTFFontOffsetTable(FILE* pfile);
CTTFFontOffsetTable(BYTE* pBuf);
private:
void Parse(BYTE* pBuf);
public:
WORD m_MajorVersion;
WORD m_MinorVersion;
WORD m_numTables;
WORD m_searchRange;
WORD m_entrySelector;
WORD m_rangeShift;
};
#define TTFFONTOFFSETTABLE_LEN (12)
CTTFFontOffsetTable::CTTFFontOffsetTable(void)
{
}
CTTFFontOffsetTable::CTTFFontOffsetTable(FILE* pFile)
{
BYTE pBuf[TTFFONTOFFSETTABLE_LEN] = {0};
fread(pBuf, 1, TTFFONTOFFSETTABLE_LEN, pFile);
this->Parse(pBuf);
}
CTTFFontOffsetTable::CTTFFontOffsetTable(BYTE* pBuf)
{
this->Parse(pBuf);
}
void CTTFFontOffsetTable::Parse(BYTE* pBuf)
{
this->m_MajorVersion = util::GetWordFromBigEndian(pBuf[0], pBuf[1]);
this->m_MinorVersion = util::GetWordFromBigEndian(pBuf[2], pBuf[3]);
this->m_numTables = util::GetWordFromBigEndian(pBuf[4], pBuf[5]);
this->m_searchRange = util::GetWordFromBigEndian(pBuf[6], pBuf[7]);
this->m_entrySelector = util::GetWordFromBigEndian(pBuf[8], pBuf[8]);
this->m_rangeShift = util::GetWordFromBigEndian(pBuf[10], pBuf[11]);
}
CTTFFontTableDirectory
class CTTFFontTableDirectory
{
public:
CTTFFontTableDirectory(BYTE* pBuf);
public:
void Parse(BYTE* pBuf);
public:
BYTE m_szTableName[4];
DWORD m_uCheckSum;
DWORD m_uOffset;
DWORD m_uLength;
UINT m_uCheckSumOffset;
};
#define TTFFONTTABLEDIRECTORY_LEN (16)
CTTFFontTableDirectory::CTTFFontTableDirectory(BYTE* pBuf)
: m_uCheckSumOffset(0)
{
Parse(pBuf);
}
void CTTFFontTableDirectory::Parse(BYTE* pBuf)
{
memcpy(this->m_szTableName, pBuf, sizeof(this->m_szTableName));
this->m_uCheckSum = util::GetDwordFromBigEndian(pBuf, 4);
this->m_uOffset = util::GetDwordFromBigEndian(pBuf, 8);
this->m_uLength = util::GetDwordFromBigEndian(pBuf, 12);
}
CTTFFontNameTableHeader
class CTTFFontNameTableHeader
{
public:
CTTFFontNameTableHeader(BYTE* pBuf);
public:
WORD m_uFSelector;
WORD m_uNRCount;
WORD m_uStorageOffset;
};
CTTFFontNameTableHeader::CTTFFontNameTableHeader(BYTE* pBuf)
{
m_uFSelector = util::GetWordFromBigEndian(pBuf[0], pBuf[1]);
m_uNRCount = util::GetWordFromBigEndian(pBuf[2], pBuf[3]);
m_uStorageOffset = util::GetWordFromBigEndian(pBuf[4], pBuf[5]);
}
CTTFFontNameRecord
class CTTFFontNameRecord
{
public:
CTTFFontNameRecord(BYTE* pBuf);
public:
WORD m_uPlatformID;
WORD m_uEncodingID;
WORD m_uLanguageID;
WORD m_uNameID;
WORD m_uStringLength;
WORD m_uStringOffset;
};
CTTFFontNameRecord::CTTFFontNameRecord(BYTE* pBUf)
{
this->m_uPlatformID = util::GetWordFromBigEndian(pBUf[0], pBUf[1]);
this->m_uEncodingID = util::GetWordFromBigEndian(pBUf[2], pBUf[3]);
this->m_uLanguageID = util::GetWordFromBigEndian(pBUf[4], pBUf[5]);
this->m_uNameID = util::GetWordFromBigEndian(pBUf[6], pBUf[7]);
this->m_uStringLength = util::GetWordFromBigEndian(pBUf[8], pBUf[9]);
this->m_uStringOffset = util::GetWordFromBigEndian(pBUf[10], pBUf[11]);
}
从字体文件中解析字体名称的函数
void GetFontName(std::string strFontFilePath)
{
std::string strName = "";
std::string strFullName = "";
std::string strSubFamilyName = "";
std::vector<std::string> AllNames;
FILE* pFile = fopen(strFontFilePath.c_str(), "rb");
A::CTTFFontOffsetTable offsettable(pFile, 0);
A::CTTFFontTableDirectory FontTableDirectory;
for (int i = 0; i < (int)offsettable.m_numTables; i++)
{
BYTE array[TTFFONTTABLEDIRECTORY_LEN];
fread(array, 1, TTFFONTTABLEDIRECTORY_LEN, pFile);
FontTableDirectory.Parse(array);
if (FontTableDirectory.GetTableName == "name")
{
fseek(pFile, (long)(FontTableDirectory.m_uOffset), SEEK_SET);
BYTE array2[TTFFONTNAMETABLEHEADER_LEN];
fread(array2, 1, TTFFONTNAMETABLEHEADER_LEN, pFile);
A::CTTFFontNameTableHeader FontNameTableHeader(array2);
for (int j = 0; j < (int)FontNameTableHeader.m_uNRCount; j++)
{
BYTE array3[TTFFONTNAMERECORD_LEN];
fread(array3, 1, TTFFONTNAMERECORD_LEN, pFile);
long position = ftell(pFile);
A::CTTFFontNameRecord FontNameRecord(array3);
if (FontNameRecord.m_uPlatformID == 3)
{
if (FontNameRecord.m_uNameID != 1)
{
if (FontNameRecord.m_uNameID != 2)
{
if (FontNameRecord.m_uNameID != 4)
{
continue;
}
}
}
fseek(pFile, (long)((FontTableDirectory.m_uOffset + FontNameRecord.m_uStringOffset + FontNameTableHeader.m_uStorageOffset)), SEEK_SET);
int nLen = FontNameRecord.m_uStringLength;
BYTE* array4 = new BYTE[nLen];
fread(array4, 1, FontNameRecord.m_uStringLength, pFile);
std::wstring wstr;
for(int i = 0; i < nLen; i+=sizeof(WCHAR))
{
char tmp[2];
tmp[0] = array4[i+1];
tmp[1] = array4[i];
wstr.append(1, *((wchar_t*)tmp));
}
delete [] array4;
string tstring = util::WString2String(wstr);
fseek(pFile, position, SEEK_SET);
if (FontNameRecord.m_uLanguageID == 1033)
{
if (1 == FontNameRecord.m_uNameID)
{
strName = tstring;
}
else if (4 == FontNameRecord.m_uNameID)
{
strFullName = tstring;
}
else
{
strSubFamilyName = tstring;
}
}
else if (1 == FontNameRecord.m_uNameID)
{
AllNames.push_back(tstring);
}
}
}
break;
}
}
bool bExists = false;
for (int i = 0; i < AllNames.size(); i++)
{
if(AllNames[i] == strName)
{
bExists = true;
}
}
if(!bExists)
{
AllNames.push_back(strName);
}
fclose(pFile);
}
本项目还在开发中,已有能运行的程序,但还不完善,欢迎感兴趣的朋友私信交流
测试程序下载地址:
https://download.csdn.net/download/cwp0508/88958928?spm=1001.2014.3001.5503