如何通过fontconfig、freetype、harfbuzz获取字体支持的Unicode脚本?
如何通过fontconfig、FreeType、HarfBuzz获取字体支持的Unicode脚本列表
当然可以,这三个库都能实现你的需求,下面分别说明具体实现方式:
HarfBuzz(最直接高效)
HarfBuzz提供了完整的Unicode脚本处理能力,结合hb_face_t可以轻松获取字体支持的脚本列表:
- 从字体文件或FreeType的
FT_Face创建hb_face_t实例; - 使用
hb_face_collect_unicodes获取字体支持的所有Unicode码点; - 遍历每个码点,用
hb_script_from_unicode将其映射到对应的hb_script_t枚举值; - 对脚本枚举值去重,得到最终的脚本列表,还可以用
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码点,再结合脚本映射逻辑实现:
- 用FreeType加载字体,得到
FT_Face; - 遍历所有可能的Unicode码点(0到0x10FFFF),用
FT_Get_Char_Index判断字体是否支持该码点; - 对支持的码点,同样可以用HarfBuzz的
hb_script_from_unicode获取脚本类型(或者自己维护Unicode到脚本的映射表); - 去重后得到脚本列表。
示例代码:
#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的字体数据库中直接存储了字体支持的脚本信息,无需遍历码点,查询更高效:
- 初始化Fontconfig配置,构造目标字体的查询模式(比如指定字体家族名);
- 使用
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
相关产品推荐
相关产品推荐

