FreeType 字体信息检查工具 - 现代C++实现
文章目录
- 获取字体的版权信息
- 工具简介
- 主要特点
- 1. 现代C++实现
- 2. 完整的功能
- 3. 健壮的错误处理
- 4. 国际化支持
- 使用说明
- 技术亮点
获取字体的版权信息
#include <iostream> // 标准输入输出流库
#include <string> // 字符串处理库
#include <vector>
#include <memory> // 智能指针库
#include <ft2build.h> // FreeType库头文件
#include FT_FREETYPE_H // FreeType主头文件
#include FT_SFNT_NAMES_H // SFNT名称表支持
#include FT_TRUETYPE_TABLES_H // TrueType表支持// 使用枚举类替代宏定义,增强类型安全
enum class NameId : uint16_t {Copyright = 0, // 版权信息IDFamily = 1, // 字体家族名称IDSubfamily = 2 // 字体子家族名称ID
};// 平台标识枚举
enum class PlatformId : uint16_t {Unicode = 0, // Unicode平台Macintosh = 1, // Macintosh平台Microsoft = 3 // Microsoft平台
};// RAII包装器管理FreeType库资源
struct FreeTypeLib {FT_Library lib; // FreeType库实例// 构造函数初始化库FreeTypeLib() {if (FT_Init_FreeType(&lib)) {throw std::runtime_error("FreeType初始化失败");}}// 析构函数释放资源~FreeTypeLib() {FT_Done_FreeType(lib);}// 类型转换运算符operator FT_Library() const {return lib;}
};// RAII包装器管理字体face资源
struct FreeTypeFace {FT_Face face; // 字体face对象// 构造函数加载字体文件FreeTypeFace(FT_Library lib, const std::string& path) {if (FT_New_Face(lib, path.c_str(), 0, &face)) {throw std::runtime_error("字体加载失败: " + path);}}// 析构函数释放资源~FreeTypeFace() {if (face) FT_Done_Face(face);}// 类型转换运算符operator FT_Face() const {return face;}
};// 打印字体基本信息
void print_font_info(FT_Face face) {std::cout << "\n字体家族: " << face->family_name // 字体家族名称<< "\n字体样式: " << face->style_name // 字体样式名称<< "\n字形数量: " << face->num_glyphs // 包含的字形数量<< "\nEM单位数: " << face->units_per_EM // 设计网格分辨率<< std::endl;
}// 解码不同平台的字符串编码
std::string decode_string(const FT_SfntName& name) {std::string result; // 存储解码结果// UTF-16BE解码lambda函数auto decode_utf16be = [](const unsigned char* str, size_t len) {std::string s;for (size_t j = 0; j + 1 < len; j += 2) {uint16_t c = (str[j] << 8) | str[j + 1]; // 组合高低字节if (c <= 0x7F) { // ASCII字符s += static_cast<char>(c);}else { // 非ASCII字符s += "\\u" + std::to_string(c); // 显示Unicode转义序列}}return s;};// 根据平台ID选择解码方式switch (static_cast<PlatformId>(name.platform_id)) {case PlatformId::Microsoft: // Microsoft平台case PlatformId::Unicode: // Unicode平台return decode_utf16be(name.string, name.string_len);case PlatformId::Macintosh: // Macintosh平台for (size_t j = 0; j < name.string_len; ++j) {unsigned char c = name.string[j];if (c >= 0x20 && c <= 0x7E) { // 可打印ASCII字符result += c;}else { // 非可打印字符result += "\\x" + std::to_string(c); // 显示十六进制转义}}break;default: // 其他平台for (size_t j = 0; j < name.string_len; ++j) {result += name.string[j]; // 直接添加字节}}return result;
}// 从名称表中提取并打印版权信息
void print_copyright_from_names(FT_Face face) {FT_UInt name_count = FT_Get_Sfnt_Name_Count(face); // 获取名称表条目数std::cout << "\n检查SFNT名称表(" << name_count << "个条目)..." << std::endl;// 遍历所有名称表条目for (FT_UInt i = 0; i < name_count; ++i) {FT_SfntName name;if (FT_Get_Sfnt_Name(face, i, &name) == 0 && // 成功获取名称条目name.name_id == static_cast<FT_UShort>(NameId::Copyright)) { // 是版权信息std::cout << "版权信息(平台" << name.platform_id<< ", 编码" << name.encoding_id << "): "<< decode_string(name) << std::endl;}}
}// 检查字体嵌入权限
void check_font_license(FT_Face face) {// 获取OS/2表(包含字体授权信息)if (auto* os2 = static_cast<TT_OS2*>(FT_Get_Sfnt_Table(face, ft_sfnt_os2))) {std::cout << "\n嵌入权限: ";switch (os2->fsType) {case 0: std::cout << "允许安装嵌入"; break;case 2: std::cout << "受限许可嵌入"; break;case 4: std::cout << "仅预览和打印嵌入"; break;case 8: std::cout << "可编辑嵌入"; break;default: std::cout << "未知权限(0x" << std::hex << os2->fsType << ")";}std::cout << std::endl;}
}
int main() {// 定义要检查的字体文件列表std::vector<std::string> font_paths = {"D:\\Font\\Alumni_Sans_SC\\AlumniSansSC-VariableFont_wght.ttf","D:\\Font\\Asta_Sans\\AstaSans-VariableFont_wght.ttf","D:\\Font\\Edu_QLD_Hand\\EduQLDHand-VariableFont_wght.ttf","D:\\Font\\Edu_SA_Hand\\EduSAHand-VariableFont_wght.ttf","D:\\Font\\Noto_Sans_JP\\NotoSansJP-VariableFont_wght.ttf","D:\\Font\\Open_Sans\\OpenSans-Italic-VariableFont_wdth,wght.ttf","D:\\Arial-Unicode-MS.ttf"};// 初始化FreeType库(RAII管理)FreeTypeLib library;// 遍历所有字体文件for (const auto& font_path : font_paths) {try {std::cout << "\n\n===== 正在检查字体: " << font_path << " =====" << std::endl;// 加载字体文件(RAII管理)FreeTypeFace face(library, font_path);// 打印字体信息print_font_info(face);// 提取并打印版权信息print_copyright_from_names(face);// 检查字体授权check_font_license(face);}catch (const std::exception& e) {std::cerr << "处理字体 " << font_path << " 时出错: " << e.what() << std::endl;continue; // 继续处理下一个字体}}return EXIT_SUCCESS;
}
工具简介
这是一个使用现代C++编写的字体信息检查工具,基于FreeType库开发,可以读取并显示字体文件的详细信息,包括:
- 基本字体信息(家族名称、样式名称等)
- 版权信息
- 字体嵌入权限
主要特点
1. 现代C++实现
- 使用RAII(资源获取即初始化)技术自动管理资源
- 采用异常处理替代传统错误码检查
- 使用枚举类增强类型安全
- 利用lambda表达式简化复杂逻辑
2. 完整的功能
- 显示字体家族名称和样式
- 提取并解码字体版权信息(支持多种编码格式)
- 检查字体嵌入权限(安装、编辑、打印等)
3. 健壮的错误处理
- 统一的异常处理机制
- 详细的错误信息提示
- 自动资源释放
4. 国际化支持
- 所有输出信息使用中文
- 完整的代码中文注释
- 支持Unicode字符显示
使用说明
- 修改代码中的
font_path
变量为您的字体文件路径 - 编译运行程序
- 程序将输出字体的详细信息
技术亮点
- 自动资源管理:通过
FreeTypeLib
和FreeTypeFace
类自动管理FreeType资源 - 智能编码处理:自动识别并处理不同平台的字体编码(Unicode、MacRoman等)
- 清晰的输出:格式化显示所有字体信息,便于阅读和理解
这个工具非常适合字体开发者、图形设计师或任何需要检查字体属性的开发人员使用。