【发布时间】:2020-06-16 22:37:08
【问题描述】:
我正在尝试使用 freetype 来枚举字体文件中的字形(名称和 unicode)。
为了获取名称,我使用的是 FT_Get_Glyph_Name。 但是我怎样才能得到字形 unicode 值呢?
我是字形和字体的新手。
【问题讨论】:
标签: freetype
我正在尝试使用 freetype 来枚举字体文件中的字形(名称和 unicode)。
为了获取名称,我使用的是 FT_Get_Glyph_Name。 但是我怎样才能得到字形 unicode 值呢?
我是字形和字体的新手。
【问题讨论】:
标签: freetype
人们会期望FT_CharMap 保存此信息:
[...] 当前激活的charmap 可用
face->charmap。
但不幸的是,它只定义了编码的种类(Unicode、MacRoman、Shift-JIS 等)。显然,查找代码的行为是在别处完成的——而.notdef 只是在该字符不可用时返回。
查看我自己的一个报告“按名称”的基于 FreeType 的 OpenType 渲染器,在可能的情况下,我在初始化序列中发现了一些代码,它存储一个字形的名称(如果有的话),否则是 Unicode。但该代码是基于字形名称的存在。
进一步思考:您可以测试每个可能的 Unicodecodepoint 并查看它是否返回 0 (.notdef) 或有效的字形索引。因此,为所有可能的字形初始化一个空表,并且仅在以下例程找到它时填写每个字符的 Unicode。
对于适度现代的字体,您只需要检查 Unicode U+FFFF;对于像繁重的中文字体(对于 Heiti SC 最高为 U+2F9F4)或 Emoji(对于 Segoe UI Emoji 最高为 U+1FA95),您需要一个更大的数组。 (从字体中获取最大数量是一个完全不同的故事,唉。决定做什么取决于你想用它做什么。)
printf ("num glyphs: %u\n", face->num_glyphs);
for (code=1; code<=0xFFFF; code++)
{
glyph_index = FT_Get_Char_Index(face, code);
/* 0 = .notdef */
if (glyph_index)
{
printf ("%d -> %04X\n", glyph_index, code);
}
}
这个简短的 C sn-p 打印出从字体字形索引到相应 Unicode 的转换表。请注意 (1) 并非字体中的所有字形都需要与它们关联的 Unicode。有些字体有大量的“额外”字形,用于 OpenType 替换(例如替代设计和自定义连字)或其他用途(例如前面提到的 Segoe UI 表情符号;它包含所有表情符号的颜色掩码)。并且 (2) 某些字形可能与多个 Unicode 字符相关联。例如,A 的字形设计既可以用作拉丁文大写字母 A,也可以用作希腊文大写字母 Alpha。
【讨论】:
Unicode 代码点在技术上并不与 TrueType/OpenType 字体中的字形一起存储。必须迭代字体中的字体cmap 表才能获得映射,这也可能是非Unicode 映射,并且可能存在指向同一字形的多个映射。好消息是,FreeType 在 API 中提供了迭代当前选定字符映射中的字形代码点的工具,这非常好documented。所以,用代码:
// Ensure an unicode characater map is loaded
FT_Select_Charmap(face, FT_ENCODING_UNICODE);
FT_ULong charcode;
FT_UInt gid;
charcode = FT_Get_First_Char(face, &gid);
while (gid != 0)
{
std::cout << std::format("Codepoint: {:x}, gid: {}", charcode, gid) << std::endl;
charcode = FT_Get_Next_Char(face, charcode, &gid);
}
利用这些信息,您可以创建从字形到 Unicode 代码点的尽力而为的映射。
【讨论】:
并非字体中的所有字形都必须具有 Unicode 代码点。在 OpenType 文本显示中,Unicode 字符序列和字形序列之间存在 m:n 映射。如果您对 Unicode 代码点和字形之间的关系感兴趣,最有意义的事情是使用从 Unicode 代码点到字体“cmap”表中包含的默认字形的映射.
有关更多背景信息,请参阅OpenType spec: Advanced Typographic Extensions - OpenType Layout。
至于字形名称,每个字形都可以有一个名称,无论它是否从“cmap”表中的代码点映射。字形名称包含在“post”表中。但并非所有字体都必须包含字形名称。例如,CJK 字体不太可能包含字形名称。
【讨论】: