Unicode - 如何确定绘制由多个 unicode 代码点组成的字素簇的正确字体?

问题描述 投票:0回答:0

我的 Linux C++ 程序需要一个非常简单的用户界面。 UI 应该只代表一个字符串列表,用户可以通过它使用键盘箭头或 j/k/h/l 键进行迭代。我知道通常不建议使用像

XLib
Xft
这样复杂的低级库,但是由于我对 UI 的需求仅意味着基本功能(带文本的矩形),所以我不想拥有巨大的像
Gtk/Qt
这样的工具包作为我程序的依赖项,所以我使用普通的旧
Xlib
来绘制 UI 和
Xft
来绘制文本。虽然我不需要复杂的 UI,但我希望我的程序能够正确显示复杂的文本,这些文本可能包括图标、表情符号、混合语言,从左到右或从右到左甚至是双向的。我还需要计算和处理文本中的“真实字符”,而不仅仅是普通字节(字符)。所以,我决定使用 ICU 库进行文本处理。这是一个相当复杂的野兽,但经过几天的阅读,我想我现在了解了 unicode 和 ICU 的基础知识。

我感兴趣的是渲染用户感知为单个字符的过程。 ICU 提供了

icu::UnicodeString
类来存储 unicode 字符串。此类的基础数据存储为一系列 16 位块(代码单元),一个 unicode 代码点可能由一个或两个(代理对)这样的代码单元组成。在
icu::CharacterIterator
的帮助下,可以根据代码单元或代码点迭代这些字符串。

我想在我的代码中实现如下:
用户设置始终首选用于绘制文本的主要字体。但如果要显示的文本包含多种语言或包含表情符号,则可能无法使用相同的字体显示整个文本,难看的矩形会出现在某些字符的位置。为了解决这个问题,我使用一些

FontConfig
函数来创建一个逻辑排序的系统字体数组,其中主字体的索引始终为 0。现在我可以使用
icu::CharacterIterator
方法遍历字符串以从字符串中提取每个代码点并调用FontConfig库中的
FcCharSetHasChar()
函数来检查主字体是否可以显示字符。如果不是,我将进一步遍历字体数组,直到找到能够绘制字符的最接近的字体(否则使用后备字体)。出于性能原因,这不是很好,但现在字符串的每个字符都可以使用
Xft
函数来显示适当的字体来绘制文本。

问题是,实际上事情要复杂得多:) 问题是用户认为的“字符”不是代码点,而是可能由多个代码点组成的所谓“字素簇”。这是我不确定如何正确处理它们的地方。好消息是 ICU 有一个类

icu::BreakIterator
可以检测文本中每个字素簇的正确边界,无论它由多少个代码点组成。好的!但是我怎样才能正确地决定使用哪种字体来绘制组成一个字素簇的多个逻辑相关代码点的块?

理论上,我可以这样做:

  1. 使用
    icu::BreakIterator
    检测字素簇的边界。
  2. 使用
    icu::UnicodeString::char32At(grapheme_cluster_start)
  3. 提取集群中的第一个代码点
  4. 使用
    FcCharSetHasChar()
    遍历字体数组以找到能够绘制此代码点的最近的 gg 字体。
  5. 使用此字体绘制整个字素簇。

但这是可靠的方法吗?如果我找到一种字体能够绘制字素簇中的第一个代码点,我是否可以假设可以使用相同的字体正确绘制整个簇?或者我应该遍历集群中的每个代码点并找到可用于绘制所有代码点的相同字体?

c++ unicode icu fontconfig
© www.soinside.com 2019 - 2024. All rights reserved.