FreeType 字体信息检查工具 - 现代C++实现

获取字体的版权信息

#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,  // 版权信息ID
    Family = 1,     // 字体家族名称ID
    Subfamily = 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. 基本字体信息(家族名称、样式名称等)
  2. 版权信息
  3. 字体嵌入权限

主要特点

1. 现代C++实现

  • 使用RAII(资源获取即初始化)技术自动管理资源
  • 采用异常处理替代传统错误码检查
  • 使用枚举类增强类型安全
  • 利用lambda表达式简化复杂逻辑

2. 完整的功能

  • 显示字体家族名称和样式
  • 提取并解码字体版权信息(支持多种编码格式)
  • 检查字体嵌入权限(安装、编辑、打印等)

3. 健壮的错误处理

  • 统一的异常处理机制
  • 详细的错误信息提示
  • 自动资源释放

4. 国际化支持

  • 所有输出信息使用中文
  • 完整的代码中文注释
  • 支持Unicode字符显示

使用说明

  1. 修改代码中的 font_path 变量为您的字体文件路径
  2. 编译运行程序
  3. 程序将输出字体的详细信息

技术亮点

  • ​自动资源管理​​:通过 FreeTypeLibFreeTypeFace 类自动管理FreeType资源
  • ​智能编码处理​​:自动识别并处理不同平台的字体编码(Unicode、MacRoman等)
  • ​清晰的输出​​:格式化显示所有字体信息,便于阅读和理解

这个工具非常适合字体开发者、图形设计师或任何需要检查字体属性的开发人员使用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

丁金金_chihiro_修行

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值