通过字体名获取字体文件

2023-05-16

由于在GLFT/FreeType中需要传入字体文件作为参数,所以需要通过字体名来寻找字体文件。现已完成,特此总结分享。
参考链接:
https://www.codeproject.com/Articles/1235/Finding-a-Font-file-from-a-Font-name
https://github.com/chaoticbob/Cinder-SdfText 具体看acquireFontNamesAndPaths,有读mac,windows,Linux的
https://github.com/pezy/QtLab/blob/fb226b6d3af5f8efcd449b1b9025c05b901b828f/QtLab/Playground/main.cpp

//.h
//通过字体名获取字体文件
BOOL GetFontFile(LPCTSTR lpszFontName, CString &strFontFile, BOOL bBold = FALSE, BOOL bItalic = FALSE);
//通过字体文件获取字体名
BOOL GetFontName(LPCTSTR lpszFontFile, CString& strFontName);
//字体中英文对照
std::map<std::string, std::string> FontFaceMap();
//.cpp
LONG GetNextNameValue(HKEY key, LPCTSTR subkey, LPTSTR szName, LPTSTR szData)
{
	static HKEY hkey = NULL;
	static DWORD dwIndex = 0;
	LONG retval;

	if (subkey == NULL && szName == NULL && szData == NULL)
	{
		//TRACE(_T("closing key\n"));
		if (hkey)
			RegCloseKey(hkey);
		hkey = NULL;
		return ERROR_SUCCESS;
	}

	if (subkey && subkey[0] != 0)
	{
		retval = RegOpenKeyEx(key, subkey, 0, KEY_READ, &hkey);
// 		if (retval != ERROR_SUCCESS)
// 		{
// 			//TRACE(_T("RegOpenKeyEx failed\n"));
// 			return retval;
// 		}
// 		else
// 		{
// 			//TRACE(_T("RegOpenKeyEx ok\n"));
// 		}
		dwIndex = 0;
	}
	else
	{
		dwIndex++;
	}

	ASSERT(szName != NULL && szData != NULL);

	*szName = 0;
	*szData = 0;

	char szValueName[MAX_PATH];
	DWORD dwValueNameSize = sizeof(szValueName) - 1;
	BYTE szValueData[MAX_PATH];
	DWORD dwValueDataSize = sizeof(szValueData) - 1;
	DWORD dwType = 0;

	retval = RegEnumValue(hkey, dwIndex, szValueName, &dwValueNameSize, NULL,
		&dwType, szValueData, &dwValueDataSize);
	if (retval == ERROR_SUCCESS)
	{
		//TRACE(_T("szValueName=<%s>  szValueData=<%s>\n"), szValueName, szValueData);
		lstrcpy(szName, (char *)szValueName);
		lstrcpy(szData, (char *)szValueData);
	}
	else
	{
		//TRACE(_T("RegEnumKey failed\n"));
	}

	return retval;
}

BOOL GetFontFile(LPCTSTR lpszFontName, CString& strDisplayName, CString& strFontFile,
	BOOL bBold /*= FALSE*/, BOOL bItalic /*= FALSE*/)
{
	if (lpszFontName && lpszFontName[0] == 0)
	{
		strFontFile = "";
		return FALSE;
	}

	CString strFontName = lpszFontName;
	if (bBold)
	{
		strFontName += " Bold";
	}

	if (bItalic)
	{
		strFontName += " Italic";
	}

	_TCHAR szName[2 * MAX_PATH];
	_TCHAR szData[2 * MAX_PATH];

// 	int nVersion;
// 	CString strVersion;
// 	GetWinVer(strVersion, &nVersion);
// 	//TRACE(_T("strVersion=%s\n"), strVersion);

	CString strFont = _T("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Fonts");

	strFontFile.Empty();

	BOOL bResult = FALSE;

	while (GetNextNameValue(HKEY_LOCAL_MACHINE, strFont, szName, szData) == ERROR_SUCCESS)
	{
		CString strName = szName;

		int nFind = strName.ReverseFind('(');
		if (nFind != -1)
		{
			strName = strName.Left(nFind-1);
		}
		CStringArray strArr;
		SplitCString(strName, "&", strArr);
		nFind = 0;
		for (int i = 1; i < strArr.GetSize(); i++)
		{
			CString strTmp = strArr[i].Trim();
			if (strTmp == strFontName)
			{
				nFind = 1;
				break;
			}
		}

		if (_strnicmp(strFontName.GetBuffer(), szName, strlen(strFontName.GetBuffer())) == 0
			|| nFind)
		{
			//TRACE(_T("found font\n"));
			strDisplayName = szName;
			strFontFile = szData;
			bResult = TRUE;
			break;
		}

		strFont.Empty();	// this will get next value, same key
	}

	GetNextNameValue(HKEY_LOCAL_MACHINE, NULL, NULL, NULL);	// close the registry key


	if (strFontFile.IsEmpty() && (strFontName.Find("Bold") != -1
		|| strFontName.Find("Italic") != -1))
	{
		strFontName.Replace(" Bold", "");
		strFontName.Replace(" Italic", "");
		//GetFontFile(strFontName, strDisplayName, strFontFile, bBold, bItalic);
		strFontFile.Empty();

		bResult = FALSE;
		strFont = _T("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Fonts");
		while (GetNextNameValue(HKEY_LOCAL_MACHINE, strFont, szName, szData) == ERROR_SUCCESS)
		{
			CString strName = szName;

			int nFind = strName.ReverseFind('(');
			if (nFind != -1)
			{
				strName = strName.Left(nFind - 1);
			}
			CStringArray strArr;
			SplitCString(strName, "&", strArr);
			nFind = 0;
			for (int i = 1; i < strArr.GetSize(); i++)
			{
				CString strTmp = strArr[i].Trim();
				if (strTmp == strFontName)
				{
					nFind = 1;
					break;
				}
			}

			if (_strnicmp(strFontName.GetBuffer(), szName, strlen(strFontName.GetBuffer())) == 0
				|| nFind)
			{
				//TRACE(_T("found font\n"));
				strDisplayName = szName;
				strFontFile = szData;
				bResult = TRUE;
				break;
			}

			strFont.Empty();	// this will get next value, same key
		}

		GetNextNameValue(HKEY_LOCAL_MACHINE, NULL, NULL, NULL);	// close the registry key
	}

	return bResult;
}

BOOL GetFontFile(LPCTSTR lpszFontName, CString &strFontFile, BOOL bBold /*= FALSE*/, BOOL bItalic /*= FALSE*/)
{
	CString strFontName = lpszFontName;

	CString strDispName;
	BOOL bRes = GetFontFile(strFontName, strDispName, strFontFile, bBold, bItalic);
	if (bRes)
	{
		return bRes;
	}

	//中英文字体名称映射
	auto mapChnEng = FontFaceMap();
	auto itFind = mapChnEng.find(strFontName.GetBuffer());
	int nFind = -1;
	if (itFind == mapChnEng.end())
	{
		nFind = strFontName.Find("Light");
		if (nFind != -1)
		{
			strFontName.Replace(" Light", "");
		}
		itFind = mapChnEng.find(strFontName.GetBuffer());
	}

	if (!bRes && itFind != mapChnEng.end())
	{
		strFontName = itFind->second.c_str(); /*G_UserData.GetAt("Fonts", strFontName)*/;
		nFind != -1 ? strFontName += " Light" : NULL;
		bRes = GetFontFile(strFontName, strDispName, strFontFile, bBold, bItalic);
	}

	if (strFontFile.IsEmpty())
	{
		strFontFile = "msyh.ttc";
	}

	return bRes;
}

BOOL GetFontName(LPCTSTR lpszFontFile, CString& strFontName)
{
	if (lpszFontFile == 0)
	{
		strFontName = "";
		return FALSE;
	}
	CString strFontFile = lpszFontFile;
	_TCHAR szName[2 * MAX_PATH];
	_TCHAR szData[2 * MAX_PATH];

	// 	int nVersion;
	// 	CString strVersion;
	// 	GetWinVer(strVersion, &nVersion);
	// 	//TRACE(_T("strVersion=%s\n"), strVersion);

	CString strFont = _T("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Fonts");

	strFontName.Empty();

	BOOL bResult = FALSE;

	while (GetNextNameValue(HKEY_LOCAL_MACHINE, strFont, szName, szData) == ERROR_SUCCESS)
	{
		if (_strnicmp(strFontFile.GetBuffer(), szData, strlen(strFontFile.GetBuffer())) == 0)
		{
			//TRACE(_T("found font\n"));
			strFontName = szName;
			bResult = TRUE;
			break;
		}

		strFont.Empty();	// this will get next value, same key
	}

	GetNextNameValue(HKEY_LOCAL_MACHINE, NULL, NULL, NULL);	// close the registry key
	int nFind = strFontName.ReverseFind('(');
	if (nFind != -1)
	{
		strFontName = strFontName.Left(nFind - 1);
	}

	CStringArray strArr;
	SplitCString(strFontName, "&", strArr);
	strFontName = strArr[0].Trim();
	nFind = strFontName.Find(" Light");
	if (nFind != -1)
	{
		strFontName.Replace(" Light", "");
	}

	strFontName.Replace(" Bold", "");
	strFontName.Replace(" Italic", "");

	auto mapChnEng = FontFaceMap();
	auto itFind = find_if(mapChnEng.begin(), mapChnEng.end(),
		[&](pair<const string, string> &a) {return a.second == strFontName.GetBuffer(); });
	
	if (itFind != mapChnEng.end())
	{
		strFontName = itFind->first.c_str();
	}

	if (nFind != -1)
	{
		strFontName += " Light";
	}

	return bResult;
}

// SafeRelease inline function.
template <class T> inline void SafeRelease(T **ppT)
{
    if (*ppT)
    {
        (*ppT)->Release();
        *ppT = NULL;
    }
}

std::wstring GetFontFaceNamePair(IDWriteLocalizedStrings* pFamilyNames, UINT32 index)
{
	std::wstring result;
    UINT32 length = 0;
    HRESULT hr = pFamilyNames->GetStringLength(index, &length);

    // Allocate a string big enough to hold the name.
    wchar_t* name = new (std::nothrow) wchar_t[length+1];
    if (name == NULL)
    {
        hr = E_OUTOFMEMORY;
    }

    // Get the family name.
    if (SUCCEEDED(hr))
    {
        hr = pFamilyNames->GetString(index, name, length+1);
    }
    if (SUCCEEDED(hr))
    {
		result = name;
    }

    delete [] name;
	return result;
}

//将wstring转换成string  
string ws2s(wstring wstr)
{
	string result;
	//获取缓冲区大小,并申请空间,缓冲区大小事按字节计算的  
	int len = WideCharToMultiByte(CP_ACP, 0, wstr.c_str(), (int)wstr.size(), NULL, 0, NULL, NULL);
	char* buffer = new char[len + 1];
	//宽字节编码转换成多字节编码  
	WideCharToMultiByte(CP_ACP, 0, wstr.c_str(), (int)wstr.size(), buffer, len, NULL, NULL);
	buffer[len] = '\0';
	//删除缓冲区并返回值  
	result.append(buffer);
	delete[] buffer;
	return result;
}

std::map<std::string, std::string> FontFaceMap()
{
	std::map<std::string, std::string> map;
    wchar_t localeName[LOCALE_NAME_MAX_LENGTH];
    // Get the default locale for this user.
    int defaultLocaleSuccess = GetUserDefaultLocaleName(localeName, LOCALE_NAME_MAX_LENGTH);
	if (!defaultLocaleSuccess || wcscmp(localeName, L"en-us") == 0)
		return map;

    IDWriteFactory* pDWriteFactory = NULL;
    HRESULT hr = DWriteCreateFactory(
            DWRITE_FACTORY_TYPE_SHARED,
            __uuidof(IDWriteFactory),
            reinterpret_cast<IUnknown**>(&pDWriteFactory)
            );

    IDWriteFontCollection* pFontCollection = NULL;
    // Get the system font collection.
    if (SUCCEEDED(hr))
    {
        hr = pDWriteFactory->GetSystemFontCollection(&pFontCollection);
		UINT32 familyCount = 0;
		// Get the number of font families in the collection.
		if (SUCCEEDED(hr))
		{
			familyCount = pFontCollection->GetFontFamilyCount();
			for (UINT32 i = 0; i < familyCount; ++i)
			{
				IDWriteFontFamily* pFontFamily = NULL;
				// Get the font family.
				if (SUCCEEDED(hr))
				{
					hr = pFontCollection->GetFontFamily(i, &pFontFamily);
				}

				IDWriteLocalizedStrings* pFamilyNames = NULL;
				// Get a list of localized strings for the family name.
				if (SUCCEEDED(hr))
				{
					hr = pFontFamily->GetFamilyNames(&pFamilyNames);
					UINT32 defaultLocaleIndex = 0;
					UINT32 EnglishIndex = 0;
					BOOL exists1 = false, exists2 = false;
					if (SUCCEEDED(hr))
					{
						HRESULT hr1, hr2;
						hr1 = pFamilyNames->FindLocaleName(localeName, &defaultLocaleIndex, &exists1);
						hr2 = pFamilyNames->FindLocaleName(L"en-us", &EnglishIndex, &exists2);
						if (SUCCEEDED(hr1) && exists1 && SUCCEEDED(hr2) && exists2 && defaultLocaleIndex != EnglishIndex)
						{
							auto defaultLocaleName = GetFontFaceNamePair(pFamilyNames, defaultLocaleIndex);
							auto EnglishName = GetFontFaceNamePair(pFamilyNames, EnglishIndex);
							map[ws2s(defaultLocaleName)] = ws2s(EnglishName);
							//std::wcout << defaultLocaleName.c_str() << "=>" << EnglishName.c_str() << std::endl;
						}

						SafeRelease(&pFamilyNames);
					}
					SafeRelease(&pFontFamily);
				}
			}
			SafeRelease(&pFontCollection);
		}
		SafeRelease(&pDWriteFactory);
    }
	return map;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

通过字体名获取字体文件 的相关文章

  • Linux - 文件复制后大小不一致的问题

    问题 xff1a 通过cp或者rsync传输文件后 xff0c 通过du s查看到的体积 xff0c 前后不一致 原因 xff1a https stackoverflow com questions 10364999 file size c
  • 基于nand flash的文件系统的整理

    一 Nandflash简介 基本概念 xff1a flash芯片 block page 附加页 1 1结构 Flash芯片的擦除以块为单位 xff0c 写以页为单位 在每个flash芯片中包括非常多的块 xff0c 同款芯片上每个块的大小相
  • 卡普的21个NP完全问题-问题描述

    以下部分为卡普21个问题的名称 xff08 来自于维基百科https zh wikipedia org wiki E5 8D A1 E6 99 AE E7 9A 84 E4 BA 8C E5 8D 81 E4 B8 80 E5 80 8BN
  • 在终端使用命令卸载交叉编译工具

    ubuntu中可以使用命令行 sudo apt install gcc arm linux gnueabi 自动安装交叉编译工具 xff0c 但是往往软件版本太过超前了 xff0c 交叉编译时候使用的命令是 arm linux gnueab
  • ubuntu系统下降低风扇转速的方式

    我的本自从装了ubuntu之后风扇就呼呼的响个不停 xff0c 看了很多教程都是说强制降低风扇转速的方式 偶然看到了转速过快的原因是因为显卡与系统自带的驱动不兼容的问题 我的显卡是nvidia xff0c 安装显卡驱动步骤如下 xff1a
  • 怎样向visual studio加入vim的强大编辑能力,让装逼防不胜防!

    经常使用vim的小伙伴知道它的强大 私认为它最大的优势就是解放了你的右手 让鼠标成为了累赘 但是其学习曲线是相当陡峭的 虽然经常使用linux系统 但是偶尔还是会迫于形势缓缓胃口的 在使用VS的时候经常不自觉的就来一串ESC shift 冒
  • JGROUPS

    package com example jgroupsdemo import jakarta annotation PostConstruct import lombok extern slf4j Slf4j import org jgro
  • android studio仿真时遇到VT-x is disabled in BIOS解决办法

    在使用android studio run app时候遇到了 xff1a Intel HAXM is required to run this AVD VT x is disabled in BIOS 的错误提示 xff0c 导致无法进行仿
  • linux系统中resolv.conf文件详解

    etc resolv conf 它是DNS客户机配置文件 xff0c 用于设置DNS服务器的IP地址及DNS域名 xff0c 还包含了主机的域名搜索顺序 该文件是由域名解析器 xff08 resolver xff0c 一个根据主机名解析IP
  • yii2.0 basic版使用CRUD生成器的时候提示错误及页面显示错误

    在使用model生成器的时候不用加命名空间 xff0c 写好表名就可以直接生成了 但是在用CRUD的时候填写完controllers和model class之后点击生成会弹出错误提示 xff1a Class 39 TelBook 39 sp
  • linux日志对应内容

    var log messages 包括整体系统信息 xff0c 其中也包含系统启动期间的日志 此外 xff0c mail xff0c cron xff0c daemon xff0c kern和auth等内容也记录在var log messa
  • 常用证书操作函数

    现有的证书大都采用X 509规范 xff0c 主要同以下信息组成 xff1a 版本号 证书序列号 有效期 拥有者信息 颁发者信息 其他扩展信息 拥有者的公钥 CA对以上信息的签名 OpenSSL实现了对X 509数字证书的所有操作 包括签发
  • MongoDB 匹配查询和比较操作符

    一 匹配查询 1 查询所有 span class token operator gt span db accounts find span class token punctuation span span class token punc
  • 我的2014——典型程序员的一年,不想再重来

    兴冲冲地拿起 xff0c 信誓旦旦的搁在一边 xff0c 以为很快就会回来 xff0c 却一晃而过 xff0c 不再回来 xff1b 我不想再重复过去 xff0c 决定去做 xff0c 写下来 题记 已经记不起我2014的年初是否有过规划
  • 我的2016——程序员年到三十,工作第四年

    看到CSDN 我的2016 主题征文活动 已经是1月6号 xff0c 而截止时间是1月8号 xff0c 对比去年的总结是在闲等活动开始 xff0c 今年在时间上真的是天差地别 但是 xff0c 一年到头 xff0c 还是需要花些时间来回顾这
  • mac下 ndk_build: command not found

    参考 http blog csdn net greenbird811 article details 7543305 在mac下调用ndk build c代码文件提示错误 fix 1 启动终端Terminal 2 进入当前用户的home目录
  • 公司分配IP地址,求主机号码的最小值和最大值。

    问题描述如下 xff1a 姐 xff1a 注意减去2的实际意义 xff1a 网络地址后的第一个主机地址是本网段的网络地址192 168 0 0 xff0c 最 后一个主机地址是本网段的广播地址192 168 255 255
  • Erlang入门

    64 author sunxu 64 copyright C 2023 lt COMPANY gt 64 doc 64 end Created 16 2月 2023 22 16 module test author 34 sunxu 34
  • IPv4地址、IPv6地址和Mac地址的位数

    xff08 1 xff09 IPv4的地址是32位 xff0c 用点分十进制表示 xff0c 每八位划分 xff0c 也就是四个0 255的十进制数 xff0c 这是很常见的 xff08 2 xff09 IPv6的地址是128位 xff0c

随机推荐

  • 用C#连接数据库的方法

    连接SQL Server数据库的方法 xff1a 1 在程序中引用System Data SqlClient命名空间 2 编写连接字符串 xff0c 格式为 xff1a Data Source 61 服务器名称 Initial Catalo
  • gcc 不支持 //注释的解决

    这段时间用slickedit写代码 xff08 windows平台下 xff0c 装了Cygwin xff09 xff0c 编译器用的gcc xff0c 但是有个问题就是用 34 34 写注释的时候 xff0c 编译的时候有错 xff1a
  • python实现按照文件名称进行文件分类

    问题 xff1a 大量名称中带有数字的图片 视频 xff0c 根据名称中数字按照一定的等差数列来排序 xff0c 并且放入指定对应的文件夹中 span class token keyword import span os span clas
  • 【深度学习】Yolov3详解笔记及Pytorch代码

    Yolov3详解笔记及Pytorch代码 预测部分网络结构backbone xff1a Darknet 53output预测结果的解码 训练部分计算loss所需参数pred是什么target是什么loss的计算过程 预测部分 网络结构 DB
  • 【深度学习】各种卷积的理解笔记(2D,3D,1x1,可分离卷积)

    卷积 1 2D卷积单通道版本多通道版本 2 3D卷积3 1x1卷积作用应用 4 卷积算法5 可分离卷积空间可分离卷积深度可分离卷积 1 2D卷积 卷积的目的是从输入中提取有用的特征 在图像处理中 xff0c 卷积可以选择多种不同的滤波器 每
  • 【深度学习】(2+1)D模型框架结构笔记

    xff08 2 43 1 xff09 D 模型框架结构笔记 SpatioTemporalConv模块结构SpatioTemporalResBlock模块结构SpatioTemporalResLayer模块结构2Plus1DNet Spati
  • 【机器学习】LR回归(逻辑回归)和softmax回归

    LR回归 xff08 逻辑回归 xff09 和softmax回归 1 LR回归Logistic回归的函数形式Logistic回归的损失函数Logistic回归的梯度下降法Logistic回归防止过拟合Multinomial Logistic
  • 【深度学习】时间注意力模块与空间注意力模块

    注意力模块 通道 xff08 时间 xff09 注意力模块空间注意力模块 通道 xff08 时间 xff09 注意力模块 为了汇总空间特征 xff0c 作者采用了全局平均池化和最大池化两种方式来分别利用不同的信息 输入是一个 H W C 的
  • 【机器学习】机器学习与统计分布的关系

    这里写目录标题 1 常见的统计学分布1 xff09 离散分布a 伯努利分布b 二项分布c 泊松分布 2 xff09 连续分布a 正态分布 xff08 高斯分布 xff09 b 均匀分布 为什么我们喜欢用 sigmoid 这类 S 型非线性变
  • AKKA入门

    1 Guardian java package com example demo import akka actor typed javadsl ActorContext import akka actor typed ActorRef i
  • 【深度学习】深入理解Batch Normalization批标准化

    Batch Normalization 1 Internal Covariate Shift 问题2 BatchNorm的本质思想1 xff09 函数图像说明2 xff09 算法3 xff09 引入参数恢复表达能力4 xff09 公式 3
  • Autolabelimg自动标注工具

    目录 前言 一 工具原理和功能 1 原理 2 功能列表 二 实战 1 下载与安装 2 配置环境 3 开始使用 4 导入模型 5 选择标注类别 6 进行自动标注 三 总结 前言 在做机器视觉有监督方面 通常会面对很多数据集 xff0c 然后去
  • anchor base,anchor free和基于分割的图像检测

    目录 1 anchor base 2 anchor free 3 基于分割 reference 1 anchor base 什么是anchor based的目标检测方法呢 如果要让你定一个规则去一个图片上框一个物体 xff0c 你会怎么做呢
  • 我的2013:从北京到石家庄的软件开发历程

    记得是正月初八那天早上离开了老家 xff0c 坐上了开往北京的大巴车去北京准备新 的一年的奋斗 xff0c 车票120元了 涨价了20 xff0c 而且还没有地方报销去了 gt lt 因为年底的时候已经离职了 考虑到各公司部门人员 xff0
  • [机器学习] ML重要概念:梯度(Gradient)与梯度下降法(Gradient Descent)

    引言 机器学习栏目记录我在学习Machine Learning过程的一些心得笔记 xff0c 涵盖线性回归 逻辑回归 Softmax回归 神经网络和SVM等等 xff0c 主要学习资料来自网上的免费课程和一些经典书籍 xff0c 免费课程例
  • TPMS胎压芯片选择:英飞凌SP370、英飞凌SP40、飞思卡尔FXTH87

    简介TPMS Tire Pressure Monitoring System xff08 TPMS xff09 xff0c 轮胎压力监测系统 xff0c TPMS的作用是在汽车行驶过程中对轮胎气压进行实时自动监测 xff0c 并对轮胎漏气和
  • 2014年计算机求职总结--准备篇

    版权所有 xff0c 转载请注明出处 xff0c 谢谢 xff01 http blog csdn net walkinginthewind article details 13000431 找工作是一个长期准备的过程 xff0c 突击是没什
  • Code::Blocks之设置字体

    设置 S gt 编辑器 D gt 常规设置 gt 编辑器设置 xff1b 在 34 字体 34 中选择 34 选择 34 按钮 xff0c 进行字体 字形 大小的选择 xff1b 确定
  • 嵌入式软件面试问题总结

    1 DCS 答 xff1a DCS一般指分散控制系统 分散控制系统是以微处理器为基础 xff0c 采用控制功能分散 显示操作集中 兼顾分而自治和综合协调的设计原则的新一代仪表控制系统 集散控制系统简称DCS 也可直译为 分散控制系统 或 分
  • 通过字体名获取字体文件

    由于在GLFT FreeType中需要传入字体文件作为参数 xff0c 所以需要通过字体名来寻找字体文件 现已完成 xff0c 特此总结分享 参考链接 xff1a https www codeproject com Articles 123