1. 程式人生 > >C++解析IconFont向量字型檔案ttf,以及無鋸齒顯示向量字型

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編譯而成。(下載地址