C++解析IconFont矢量字体文件ttf,以及无锯齿显示矢量字体

一、下载矢量字体文件TTF

1、可以使用集成好的矢量字体,如FontAwesome、openwebicons、IcoMoon-Free、typicons……

只要去搜索关键字,找到对应的官网即可下载到,其中FontAwesome使用最为广泛。

2、国内最大的IconFont下载基地:阿里巴巴矢量图标库。

将喜欢的矢量字体图标加入到购物车,然后点击下载代码即可,目前是免费的。

二、使用C++解析TTF文件

首先加载Gdiplus必备三行代码

#include "gdiplus.h"
#pragma comment(lib,"gdiplus.lib")
using namespace Gdiplus;

1、获取字体名称(gdiplus初始化的代码最好放在程序的初始化中,且全局只能初始化一次)

BOOL GetFontName(LPCTSTR pFilePath, LPTSTR pFontName) {
	// 初始化gdiplus
	ULONG_PTR m_gdiplusToken;
	Gdiplus::GdiplusStartupInput gdiplusStartupInput;
	Gdiplus::GdiplusStartup(&m_gdiplusToken, &gdiplusStartupInput, NULL);

	// 添加字体
	Gdiplus::PrivateFontCollection pCollection;
	if (Gdiplus::Status::Ok != pCollection.AddFontFile(pFilePath)) return FALSE;
	
	int count = pCollection.GetFamilyCount();
	if (count == 0) return FALSE;

	int found = 0;
	Gdiplus::FontFamily* pFontFamily = (Gdiplus::FontFamily*)malloc(count * sizeof(Gdiplus::FontFamily));
	pCollection.GetFamilies(count, pFontFamily, &found);
	if (found == 0) {
		free(pFontFamily);
		return FALSE;
	}
	// 获取字体名称
	pFontFamily->GetFamilyName(pFontName);
	free(pFontFamily);

	// 卸载gdiplus
	Gdiplus::GdiplusShutdown(m_gdiplusToken);
	return TRUE;
}

2、获取字体所包含的所有图标的unicode代码

std::vector<wchar_t> GetIconNames(LPCTSTR pFilePath,LPCTSTR pFontName) {
	// 加载字体文件
	::AddFontResourceEx(pFilePath, FR_PRIVATE, 0);

	std::vector<wchar_t> vcNames;
	// 临时获取一个HDC
	HDC hDc = ::GetDC(NULL);
	// 创建所加载的文件的字体
	HFONT hfont = ::CreateFont(20, 0, 0, 0, FW_HEAVY, 0, 0, 0, DEFAULT_CHARSET,\
		OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, FF_DONTCARE, pFontName);
	// 载入到当前的HDC中
	HFONT oldFont = (HFONT)::SelectObject(hDc, (HGDIOBJ)hfont);
	// 获取该ttf字体文件所有的全部unicode字符
	DWORD  size = ::GetFontUnicodeRanges(hDc, NULL);
	GLYPHSET * pGlyphSet = (GLYPHSET*) new BYTE[size];
	pGlyphSet->cbThis = size;
	size = GetFontUnicodeRanges(hDc, pGlyphSet);
	for (int i = 0; i < pGlyphSet->cRanges; i++)
		for (int j = 0; j < pGlyphSet->ranges[i].cGlyphs; j++)
			vcNames.emplace_back(j + pGlyphSet->ranges[i].wcLow);
	::SelectObject(hDc, (HGDIOBJ)oldFont);
	::ReleaseDC(NULL, hDc);
	::RemoveFontResourceEx(pFilePath, FR_PRIVATE, 0);
	delete pGlyphSet;
	return vcNames;
}
使用如下:

void Cmfc2Dlg::OnBnClickedOk()
{
	TCHAR * pFontPath = _T("F:\\MyCode\\CPP\\DuiLib\\Fonts\\fontawesome-webfont.ttf");
	TCHAR fontName[MAX_PATH] = {0};
	if (!GetFontName(pFontPath, fontName)) return;

	auto iconNames = GetIconNames(pFontPath, fontName);
	for (auto iconName : iconNames)
	{
		TRACE(_T("%x\n"), iconName);
	}
}

三、使用GdiPlus绘制无锯齿的矢量图标

使用Gdiplus绘制,需要将gdiplus初始化的代码放在应用初始化中,且只初始化一次,不然会报错。

1、gdiplus属性

	ULONG_PTR m_gdiplusToken;
	Gdiplus::GdiplusStartupInput gdiplusStartupInput;
2、初始化

Gdiplus::GdiplusStartup(&m_gdiplusToken, &gdiplusStartupInput, NULL);
3、程序退出时

Gdiplus::GdiplusShutdown(m_gdiplusToken);

4、绘制代码如下:

void Cmfc2Dlg::OnBnClickedOk()
{
	TCHAR * pFontPath = _T("F:\\MyCode\\CPP\\DuiLib\\Fonts\\fontawesome-webfont.ttf");
	TCHAR fontName[MAX_PATH] = {0};
	if (!GetFontName(pFontPath, fontName)) return;

	auto iconNames = GetIconNames(pFontPath, fontName);

	HDC hDC = ::GetDC(m_hWnd);

	// 添加字体
	Gdiplus::PrivateFontCollection pCollection;
	if (Gdiplus::Status::Ok != pCollection.AddFontFile(pFontPath)) return;

	Gdiplus::Font font(fontName, 16, Gdiplus::FontStyleRegular, Gdiplus::UnitPixel, &pCollection);

	int i = 0 , j = 0;
	for (auto iconName : iconNames)
	{
		wchar_t iconFont[2] = {0};
		iconFont[0] = iconName;
		Gdiplus::Graphics graphics(hDC);
		graphics.SetTextRenderingHint(Gdiplus::TextRenderingHintAntiAlias);
		Gdiplus::SolidBrush solidBrush(Gdiplus::Color(255,0,0,0));
		graphics.DrawString(iconFont, 1, &font,Gdiplus::PointF(i,j), &solidBrush);
		i += 50;
		if (i % 500 == 0) {
			i = 0;
			j += 50;
		}
	}
}

5、绘制的效果图



四、矢量字体查看工具,使用Duilib编译而成。(下载地址


















猜你喜欢

转载自blog.csdn.net/wyansai/article/details/78888075