You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过fontconfig、freetype、harfbuzz获取字体支持的Unicode脚本?

如何通过fontconfig、FreeType、HarfBuzz获取字体支持的Unicode脚本列表

当然可以,这三个库都能实现你的需求,下面分别说明具体实现方式:

HarfBuzz(最直接高效)

HarfBuzz提供了完整的Unicode脚本处理能力,结合hb_face_t可以轻松获取字体支持的脚本列表:

  1. 从字体文件或FreeType的FT_Face创建hb_face_t实例;
  2. 使用hb_face_collect_unicodes获取字体支持的所有Unicode码点;
  3. 遍历每个码点,用hb_script_from_unicode将其映射到对应的hb_script_t枚举值;
  4. 对脚本枚举值去重,得到最终的脚本列表,还可以用hb_script_to_string将枚举转为可读的脚本名称(如latn对应拉丁、cyrl对应西里尔)。

示例代码:

#include <harfbuzz/hb.h>

hb_face_t *face = hb_face_create_from_file("your-font.ttf", 0);
if (!face) return;

hb_set_t *unicode_set = hb_set_create();
hb_face_collect_unicodes(face, unicode_set);

hb_set_t *script_set = hb_set_create();
hb_codepoint_t cp = HB_SET_VALUE_INVALID;
while (hb_set_next(unicode_set, &cp)) {
    hb_script_t script = hb_script_from_unicode(cp);
    if (script != HB_SCRIPT_UNKNOWN) {
        hb_set_add(script_set, (hb_codepoint_t)script);
    }
}

// 遍历输出所有支持的脚本
hb_codepoint_t script_code = HB_SET_VALUE_INVALID;
while (hb_set_next(script_set, &script_code)) {
    const char *script_name = hb_script_to_string((hb_script_t)script_code);
    printf("Supported script: %s\n", script_name);
}

// 资源清理
hb_set_destroy(unicode_set);
hb_set_destroy(script_set);
hb_face_destroy(face);

FreeType

FreeType本身没有直接返回脚本列表的API,但可以通过遍历字体支持的Unicode码点,再结合脚本映射逻辑实现:

  1. 用FreeType加载字体,得到FT_Face;
  2. 遍历所有可能的Unicode码点(0到0x10FFFF),用FT_Get_Char_Index判断字体是否支持该码点;
  3. 对支持的码点,同样可以用HarfBuzz的hb_script_from_unicode获取脚本类型(或者自己维护Unicode到脚本的映射表);
  4. 去重后得到脚本列表。

示例代码:

#include <ft2build.h>
#include FT_FREETYPE_H
#include <harfbuzz/hb.h>

FT_Library ft_lib;
FT_Face ft_face;
if (FT_Init_FreeType(&ft_lib) != 0) return;
if (FT_New_Face(ft_lib, "your-font.ttf", 0, &ft_face) != 0) {
    FT_Done_FreeType(ft_lib);
    return;
}

hb_set_t *script_set = hb_set_create();
for (hb_codepoint_t cp = 0; cp <= 0x10FFFF; cp++) {
    if (FT_Get_Char_Index(ft_face, cp) != 0) {
        hb_script_t script = hb_script_from_unicode(cp);
        if (script != HB_SCRIPT_UNKNOWN) {
            hb_set_add(script_set, (hb_codepoint_t)script);
        }
    }
}

// 处理脚本列表...

FT_Done_Face(ft_face);
FT_Done_FreeType(ft_lib);
hb_set_destroy(script_set);

Fontconfig

Fontconfig的字体数据库中直接存储了字体支持的脚本信息,无需遍历码点,查询更高效:

  1. 初始化Fontconfig配置,构造目标字体的查询模式(比如指定字体家族名);
  2. 使用FcFontList获取匹配的字体,提取FC_SCRIPT属性,该属性返回的是脚本的字符串标识符(如latn、han)。

示例代码:

#include <fontconfig/fontconfig.h>

FcConfig *config = FcInitLoadConfigAndFonts();
if (!config) return;

FcPattern *pattern = FcPatternCreate();
FcPatternAddString(pattern, FC_FAMILY, (FcChar8 *)"YourFontFamily");

FcObjectSet *obj_set = FcObjectSetBuild(FC_SCRIPT, NULL);
FcFontSet *font_set = FcFontList(config, pattern, obj_set);

if (font_set && font_set->nfont > 0) {
    FcPattern *font = font_set->fonts[0];
    FcChar8 **scripts;
    int script_count;
    if (FcPatternGetStringArray(font, FC_SCRIPT, 0, &scripts, &script_count) == FcResultMatch) {
        for (int i = 0; i < script_count; i++) {
            printf("Supported script: %s\n", scripts[i]);
        }
    }
}

// 资源清理
FcFontSetDestroy(font_set);
FcObjectSetDestroy(obj_set);
FcPatternDestroy(pattern);
FcConfigDestroy(config);

方案选择建议

  • 如果你已经在项目中使用HarfBuzz,优先选择HarfBuzz的方案,逻辑清晰且无需额外依赖;
  • 若需要快速查询系统字体的脚本支持,Fontconfig的方式最直接,不需要处理底层码点;
  • FreeType的方案适合没有引入HarfBuzz和Fontconfig的场景,但需要自己处理码点遍历,效率稍低。

内容的提问来源于stack exchange,提问作者andre487

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 16:10:16