【问题标题】:Glyph to unicode string translation字形到 unicode 字符串的翻译
【发布时间】:2014-08-10 04:57:12
【问题描述】:

给定特定字体的字形索引,我需要获取该字形的 Unicode 翻译。为了构建字形到 unicode 的翻译,我对整个 unicode 范围使用 GetGlyphIndices,并根据结果构建反向翻译(字形到 unicode 字符映射)。但是,这给了我单个字形到单个 unicode 字符之间的转换,例如,我可以看到在印地语中,两个 unicode 字符可以由一个字形表示。

例如,在单词 namaste (नमस्ते) 中有 6 个 unicode 字符由 5 个字形表示(中间的两个 unicode 字符由一个字形表示)。我可以通过附加到 notepad.exe、在 ExtTextOut 中插入断点并从记事本打印该单词来看到这一点。

有什么方法可以将字形转换为 unicode 字符串(以防字形表示多个 unicode 字符)?

【问题讨论】:

  • 我已经在这里发布了一个答案,但我很好奇你为什么认为你需要这样做?您已经有输入的 Unicode;为什么需要从字形映射回它们?
  • 感谢您的回答!我去看看资源。实际上我没有输入的 unicode,只有字形(我正在挂钩 ExtTextOut,并且从挂钩的函数中我想从给定的字形返回到 unicode 字符)
  • 我很难理解您只能访问输出字形的情况。当然,在您的流程中的某个地方存在输入字符串(Unicode),即在上面的示例中,在流程的早期挂钩,在调用 ExtTextOut 之前获取输入字符串(lpString,cbCount)?也许您可以更详细地解释整个过程以及您的代码适合的位置?
  • 这是真的,我也尝试过这种方法 - 但并非在所有情况下我都能理解输入字符串在何处转换为字形。根据 ExtTextOut 文档,字形是通过调用 GetCharacterPlacement 获得的。但是,当我调试应用程序(例如 IE、Chrome)时,我发现它们没有调用此函数,而且我不确定它们究竟是如何从 unicode 字符串中获取字形的。

标签: winapi fonts gdi glyph


【解决方案1】:

1) 对于所有非常简单的情况,您应该使用 Uniscribe 函数(不是 GetGlyphIndices)将字符串(Unicode 序列)转换为字形。这在 GetGlyphIndices 的文档中有说明:http://msdn.microsoft.com/en-us/library/windows/desktop/dd144890(v=vs.85).aspx

2) 无法在所有情况下可靠地执行您想要执行的操作。即使在大多数情况下。这是称为复杂脚本整形的结果,它将输入 Unicode 序列转换为输出字形序列。这是使用字体数据中的许多表来完成的。最感兴趣的两个是 cmap 和 GSUB。

cmap 将 Unicode 值映射到特定于字体的字形。 cmap 可以指定多个 Unicode 映射到单个字形(多映射)。这是许多字体中常用的方案。此外,字体中的许多字形甚至可能没有映射到 cmap 中。因此,仅凭这一点,您无法可靠地将字形反向映射到单个 Unicode。

但它变得更加困难:GSUB 可以指定许多规则,并且可以将一个输入字形转换为多个输出字形,或者将一系列输入字形转换为一个输出字形。它甚至可以指定发生转换的上下文(例如,它可以说“将'A'转换为'B',但仅当'A'前面有'C'时”,所以CA -> CB但是 DA -> DA)。在某些情况下,特别是对于印地语和其他印度语语言,输出字形序列甚至可能与逻辑 Unicode 输入序列的顺序不同。最终结果是字形的输出序列可能映射回单个 Unicode,或多个 Unicode,或者根本没有。或许可以解码 GSUB 的规则 + 脚本整形引擎的逻辑来缩小范围(不适合精神弱者的冒险!),但问题仍然是多输入 Unicode 可能会结束最多解析到相同的输出字形。

底线:最好将转换字符串的过程 -> 字体特定字形视为单向之旅。

为了更好地理解这些概念,我强烈建议您阅读在 Windows 中实现的复杂脚本整形:http://www.microsoft.com/typography/otspec/TTOCHAP1.htm。至于应用程序中的编码,Uniscribe 参考资料也非常丰富:http://msdn.microsoft.com/en-us/library/windows/desktop/dd374091(v=vs.85).aspx

【讨论】:

    猜你喜欢
    • 2015-03-27
    • 2015-01-13
    • 2018-05-09
    • 1970-01-01
    • 2010-10-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-20
    相关资源
    最近更新 更多