PPT转H5系列(八)----从ttf格式的字体文件获取字体名称

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

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值