找到渲染代码点的最佳字体

找到渲染代码点的最佳字体

如何找到合适的字体来渲染 unicode 代码点?

gnome-terminal找到像 « 这样的字符

答案1

使用字体配置,

> fc-list ':charset=<hex_code1> <hex_code2>'

例如

> fc-list ':charset=2713 2717'

将显示任何包含 ✓ 和 ✗ 的字体文件名。

获取与字符对应的代码点使用(例如)

> printf "%x" \'✓
2713>

这使用了一个有点模糊的特征POSIXprintf实用程序:

如果前导字符是单引号或双引号,则该值应为单引号或双引号后面的字符的基础代码集中的数值。

综合起来,

> printf '%x' \'✓ | xargs -I{} fc-list ":charset={}"

这使用xargs -I标志来替换{}来自 的名称stdin。所以这实际上可以归结为:

> fc-list ":charset=2713"

答案2

这不一定是最好的方法,而且它肯定不是用户友好的,但它很容易实现:这里有一个 Python 脚本来完成它。

安装Python 字体配置图书馆。从您的发行版中获取它(例如sudo apt-get install python-fontconfig在 Debian 及其衍生版本上)或将其安装在您的主目录中(pip install --user python-fontconfig)。然后您可以运行此脚本(将其保存fc-search-codepoint在您的目录中PATH,例如通常~/bin,并使其可执行):

#!/usr/bin/env python2
import re, sys
import fontconfig
if len(sys.argv) < 1:
    print('''Usage: ''' + sys.argv[0] + '''CHARS [REGEX]
Print the names of available fonts containing the code point(s) CHARS.
If CHARS contains multiple characters, they must all be present.
Alternatively you can use U+xxxx to search for a single character with
code point xxxx (hexadecimal digits).
If REGEX is specified, the font name must match this regular expression.''')
    sys.exit(0)
characters = sys.argv[1]
if characters.startswith('U+'):
    characters = unichr(int(characters[2:], 16))
else:
    characters = characters.decode(sys.stdout.encoding)
regexp = re.compile(sys.argv[2] if len(sys.argv) > 2 else '')

font_names = fontconfig.query()
found = False
for name in font_names:
    if not re.search(regexp, name): continue
    font = fontconfig.FcFont(name)
    if all(font.has_char(c) for c in characters):
        print(name)
        found = True

sys.exit(0 if found else 1)

用法示例:

$ fc-search-codepoint 

答案3

最终 gnome-terminal 使用字体配置到(除其他外):

...即使您已经安装了数千种字体,也可以在已安装的字体集中高效快速地找到所需的字体...

在里面API文档您可以找到用于查询字体字符范围和对字符范围进行操作的函数,但文档是如此神秘,以至于我永远无法弄清楚不同的函数集如何相互关联。如果我需要更深入地研究,我宁愿查看其他软件中的使用示例,也许静脉血栓栓塞(gnome-terminal 中使用的终端仿真库)。

中间的另一个图书馆静脉血栓栓塞字体配置潘戈 “......用于布局和渲染文本的库,重点是国际化......”。现在我想起来了,它听起来包含了你所追求的大部分逻辑。

pango中的字符覆盖功能是通过以下方式实现的覆盖图(“在 Pango 中通常需要确定特定字体是否可以表示特定字符​​,以及它可以在多大程度上表示该字符。PangoCoverage 是一种用于表示该信息的数据结构。”),但是在决定用什么字体渲染什么字形时可能涉及更复杂的细节。我猜静脉血栓栓塞症依靠潘戈用适当的字体渲染字符串潘戈用途字体配置(或其他支持的字体后端)根据各种逻辑找到最合适的字体潘戈本身和/或后端。

答案4

我更改了代码来检查字体是否包含特定字符串的所有字符。因此可以调用它fc-search-codepoint "$fontname" "$string",成功时返回退出代码 0,否则返回 1。字体名称可以从fc-query /path/to/FontSandMonoBoldOblique.ttfImagemagick 或 Imagemagick 中检索convert -list font。我用它来检查用户选择的字符串是否可以使用用户选择的字体呈现,如果命令失败,则使用后备字体。

#!/usr/bin/env python2
import re
import sys
import os
import fontconfig
if len(sys.argv) < 3:
    print("Usage: " + sys.argv[0] + " 'Fontname-Bold' 'String to check'")
    sys.exit(0)

font_name = sys.argv[1].decode('utf-8')
string = sys.argv[2].decode('utf-8')

if '-' in font_name:
        font_name = font_name.split('-')
        font_style = font_name[-1]
        font_name = ''.join(font_name[:-1])
else:
        font_style = ""

font_names = fontconfig.query()
for name in font_names:
    font = fontconfig.FcFont(name)
    if not len(font.family) > 0:
        continue
    for item in font.family:
        if item[1] == unicode(font_name):
            if len(font_style) == 0:
                match = "yes"
            else:
                for item in font.style:
                    if item[1] == unicode(font_style):
                        match = "yes"
            try:
                match
            except NameError:
                continue
            if all(font.has_char(c) for c in string):
                sys.exit(0)
            else:
                sys.exit(1)
print >> sys.stderr, "font not found: " + font_name + " " + font_style
sys.exit(1)

相关内容