VS编程查看字体字符unicode与字形编码索引值index关系、显示字体字符

wxleasyland@139.com

2021.12

unicode型字体文件中,有字符unicode与字形编码索引值index的关系。

一、得到字体中字符unicode与字形编码索引值index的关系

参考别人的《GetFontUnicodeRanges获取指定字体文件中的字符》、《字样索引(Glyph Index)与字符之间的转换》。

这个程序中有CreateFont()时要指定字体准确名称的问题,可双击字体查看这个名称,比较麻烦,暂无解决。

在VS的MFC的对话框的按钮的程序中(设置中字符集采用多字节):

    CString cstr, cstrin, cstrout;

    GetDlgItem(IDC_EDIT1)->GetWindowText(cstrin);

    HDC hdc = ::GetDC(0);

    DWORD  size = 0;

    //wchar_t myChar[200000];    //unicode char

    wchar_t *myChar=(wchar_t*) new BYTE[2000000];

    int error2 = AddFontResourceEx(cstrin, FR_PRIVATE, 0);

    if (!error2)

    {

       MessageBox("字体加载失败AddFontResourceEx!");

       return;

    }

    HFONT hfont = NULL;

     hfont = CreateFont(20, 0, 0, 0, FW_HEAVY, 0, 0, 0, DEFAULT_CHARSET, \

       OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, FF_DONTCARE, _T("Symath"));

//注:CreateFont中要把字体名称改成你的字体的准确名称,如果名称乱输或不对,则函数也会成功,会得到一个很大的字体,未研究是什么字体

    if(hfont==NULL)

    {

       MessageBox("字体加载失败 CreateFont!");

       return;

    }

    HFONT oldFont = (HFONT)SelectObject(hdc, hfont);

    //第一次调用,获得所需空间大小

    size = GetFontUnicodeRanges(hdc, NULL);

    // 分配空间

    GLYPHSET *pGlyphSet = (GLYPHSET*) new BYTE[size];

    pGlyphSet->cbThis = size;

    //第二次调用,获得字库相关信息

    size = GetFontUnicodeRanges(hdc, pGlyphSet);

    int i; int j;

    int q = 0;

    for (i = 0; i < pGlyphSet->cRanges; i++)

    {

       for (j = 0; j < pGlyphSet->ranges[i].cGlyphs; j++)

       {

           myChar[q] = j + pGlyphSet->ranges[i].wcLow;//这就是包含的字符

           q++;

       }

    }

    //最终得到q是字符总数

    cstr.Format("q=%d", q);

    MessageBox(cstr);

    WORD gp[100];

    cstr.Format("unicode\tindex\r\n", q);

    cstrout += cstr;

    for (i = 0; i < q; i++)

    {

       GetGlyphIndicesW(hdc, &myChar[i], 1, gp, GGI_MARK_NONEXISTING_GLYPHS);

       cstr.Format("%04X\t%04X\r\n", (WORD)myChar[i], gp[0]   );

       cstrout += cstr;

    }

    SetDlgItemText(IDC_EDIT9, cstrout);

二、显示字体中的所有字符

根据别人的《C++解析IconFont矢量字体文件ttf,以及无锯齿显示矢量字体》。

程序是采用gdi接口来编的,在vs2017下有一些错误,修改了一下。

这个程序解决了CreateFont()时要指定字体名称的问题,可以根据这个程序,再用GetGlyphIndicesW()来得到index关系。

另外,有一个情况:字体中有字符存在,但没有字形,即字符显示出来是空的。这种情况很常见。

在VS的MFC对话框程序中成功。

(设置中字符集采用UNICODE)

程序前面加上:

#include <vector>

#include "gdiplus.h"

#pragma comment(lib,"gdiplus.lib")

using namespace Gdiplus;

加上全局变量:

// 初始化gdiplus

ULONG_PTR m_gdiplusToken;

Gdiplus::GdiplusStartupInput gdiplusStartupInput;

OnInitDialog()中加上:

       // 初始化gdiplus

    Gdiplus::GdiplusStartup(&m_gdiplusToken, &gdiplusStartupInput, NULL);

加上2个子函数程序:

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

BOOL GetFontName(LPCTSTR pFilePath, LPTSTR pFontName)

{

    // 添加字体

    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);             //这里好像需要字符串是WCHAR才行!!!!!所以工程要设置 成 unicode环境

    if (found == 0) {

       free(pFontFamily);

       return FALSE;

    }

    // 获取字体名称

    pFontFamily->GetFamilyName(pFontName);

    free(pFontFamily);

    return TRUE;

}

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

std::vector<WCHAR> GetIconNames(LPCTSTR pFilePath, LPCTSTR pFontName)

{

    // 加载字体文件

    ::AddFontResourceEx(pFilePath, FR_PRIVATE, 0);

    std::vector<WCHAR> 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;

}

在按钮程序中,加上:

    CString pFontPath;

    GetDlgItemText(IDC_EDIT1, pFontPath);

    //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 wc_iconFont[2] = { 0 };

       wc_iconFont[0] = iconName;

      

       Gdiplus::Graphics graphics(hDC);

       graphics.SetTextRenderingHint(Gdiplus::TextRenderingHintAntiAlias);

       Gdiplus::SolidBrush solidBrush(Gdiplus::Color(255, 0, 0, 0));

      

       graphics.DrawString( wc_iconFont, 1, &font, Gdiplus::PointF(i, j), &solidBrush);     //画出wc_iconFont这个字符(实际是个字串)

      

       i += 50;

       if (i % 500 == 0)

       {

           i = 0;

           j += 50;

       }

    }

在程序退出的OnClose()代码中,加上:

       // 卸载gdiplus

    Gdiplus::GdiplusShutdown(m_gdiplusToken);

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值