可变字体(Variable Font)命名实例解析工具 —— 基于 FreeType2 的 C++ 实现
文章目录
代码大纲
一、项目概述
本程序是一个基于 FreeType2 库的 C++ 工具,用于解析 TrueType/OpenType 格式的可变字体(Variable Font),提取其所有命名实例(Named Instances) 的名称信息与设计坐标。通过读取字体的 SFNT 名称表(Name Table)并进行编码转换,实现跨平台字体名称的正确解码,最终输出每个实例的多种名称及其对应的轴坐标(如字重、字宽等)。
二、技术栈与依赖
- 核心库:FreeType2(
freetype.h及相关模块) - 编码处理:UTF-16BE → UTF-16 → UTF-8(使用 Windows API)
- 图像支持(预留):JPEG 库(
jpeglib.h,当前未使用) - 平台:Windows(依赖
windows.h实现编码转换) - 语言标准:C++11 或更高(使用
std::map、std::set、范围 for 循环等)
三、关键功能模块
1. 编码转换工具函数
-
utf16_to_utf8(const wchar_t*, size_t)
使用WideCharToMultiByte将 UTF-16 宽字符串转换为 UTF-8 编码的std::string。 -
utf16be_to_utf16(const uint8_t*, size_t)
将大端序(Big-Endian)的 UTF-16 字节流转换为本地字节序的std::wstring,用于处理 SFNT 表中的 Unicode 字符串。
2. SFNT 名称表解码函数
decode_sfnt_name(const FT_SfntName&)
根据platform_id和encoding_id对字体名称进行智能解码:- Macintosh 平台:支持 Roman 编码
- Microsoft 平台:支持 Unicode 和 Symbol 编码(UTF-16BE)
- Apple Unicode 平台:直接按 UTF-16BE 解析
- ISO 平台:原始字节转字符串
- 默认回退机制确保兼容性
3. 可变字体命名实例提取
get_variable_font_instances(FT_Face)
核心函数,执行以下操作:- 验证字体是否为多主/可变字体(
FT_HAS_MULTIPLE_MASTERS) - 获取
FT_MM_Var结构,包含轴(axis)与命名实例(named styles) - 遍历每个命名实例:
- 通过
strid从名称表获取主名称 - 遍历所有名称条目,收集家族名、子家族名、全名、PostScript 名等
- 若无有效名称,则生成默认名称(如 “实例_0”)
- 通过
- 返回
map<int, set<string>>:实例索引 → 名称集合
- 验证字体是否为多主/可变字体(
4. 主函数流程(main)
- 初始化 FreeType 库
- 加载指定路径的可变字体文件(
.ttf或.otf) - 获取并验证可变字体信息(
FT_MM_Var) - 调用
get_variable_font_instances提取实例信息 - 输出结果:
- 实例索引
- 所有解析出的名称
- 每个实例在各设计轴上的坐标值(归一化为浮点数)
- 释放资源并退出
四、输出示例
找到 5 个命名实例:
实例 0:
- Thin
- Regular
- Noto Sans SC Thin
设计坐标: Weight=100.0 Wdth=100.0
实例 1:
- ExtraLight
- Noto Sans SC ExtraLight
设计坐标: Weight=200.0 Wdth=100.0
...
五、潜在改进方向
- 跨平台编码转换:当前依赖 Windows API,可替换为
iconv或std::wstring_convert实现跨平台支持。 - 错误处理增强:增加文件存在性检查、权限验证等。
- 输出格式扩展:支持 JSON 或 CSV 输出,便于集成到其他系统。
- GUI 支持:结合图形库展示字体预览。
- 动态轴信息输出:打印轴的最小/最大/默认值。
六、编译与运行要求
- 安装 FreeType2 开发库(建议版本 2.10+)
- 链接 FreeType2 库(如
freetyped.lib或libfreetype.a) - 使用支持 C++11 的编译器(如 MSVC、g++、clang++)
- 示例编译命令(MSVC):
cl main.cpp /I"path/to/freetype/include" /link "path/to/freetype/lib/freetyped.lib"
七、总结
本程序展示了如何利用 FreeType2 深度解析现代可变字体的元数据,尤其在处理多语言字体名称时,正确实现 UTF-16 编码转换至关重要。该工具可用于字体开发、调试、自动化测试或字体信息提取系统中。
// FreeType2基础头文件
#include <ft2build.h>
// FreeType多主字体(可变字体)支持头文件
#include FT_FREETYPE_H
#include FT_MULTIPLE_MASTERS_H
// C++标准容器和字符串处理
#include <map> // 映射容器
#include <string> // 字符串类
#include <vector> // 动态数组
#include <iostream> // 输入输出流
#include <set>
// FreeType SFNT名称表相关头文件(处理字体命名信息)
#include FT_SFNT_NAMES_H
#include <ft2build.h>
#include FT_FREETYPE_H
#include FT_MULTIPLE_MASTERS_H
// FreeType TrueType/OpenType表相关头文件
#include <ft2build.h>
#include FT_FREETYPE_H
#include FT_TRUETYPE_TAGS_H // TrueType标签定义
#include FT_SFNT_NAMES_H // SFNT名称表
#include FT_TYPE1_TABLES_H // Type1字体表
#include FT_MULTIPLE_MASTERS_H // 多主字体支持
#include FT_TRUETYPE_IDS_H // TrueType标识符
// JPEG图像处理库
#include <jpeglib.h>
// Windows API头文件
#include <windows.h>
/**
* UTF-16转UTF-8编码转换函数(使用Windows API实现)
* @param utf16_str UTF-16编码的宽字符指针
* @param length 输入字符串长度
* @return 转换后的UTF-8字符串
*/
std::string utf16_to_utf8(const wchar_t* utf16_str, size_t length) {
// 空指针或零长度检查
if (!utf16_str || length == 0) return "";
// 计算需要的UTF-8缓冲区大小
int utf8_len = WideCharToMultiByte(CP_UTF8, 0, utf16_st

1万+

被折叠的 条评论
为什么被折叠?



