Answers:
这不一定是最好的方法,并且肯定不是用户友好的,但是很容易上手:这是一个Python脚本来实现。
安装Python-fontconfig库。可以从您的发行版中获取它(例如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 🉃⼼😻🕲🝤
$ echo $?
1
我没有所有这些字符的字体。
$ fc-search-codepoint U+1F64D
/usr/share/fonts/truetype/unifont/unifont_upper.ttf
/usr/share/fonts/truetype/unifont/unifont_upper_csur.ttf
#!/usr/bin/env python
到#!/usr/bin/env python2
按PEP 394
python3
;我只是在此答案的底部写了一个较小的版本。
使用fontconfig,
> fc-list ':charset=<hex_code1> <hex_code2>'
例如
> fc-list ':charset=2713 2717'
将显示包含✓和✗的所有字体文件名。
要获取与字符相对应的代码点,请使用(例如)
> printf "%x" \'✓
2713>
这将使用有点模糊功能
的的POSIX printf
实用工具:
如果前导字符是单引号或双引号,则该值应是单引号或双引号后的字符的基础代码集中的数值。
在一起
> printf '%x' \'✓ | xargs -I{} fc-list ":charset={}"
这将使用该xargs
-I
标志替换{}
来自的名称stdin
。因此,这实际上可以归结为:
> fc-list ":charset=2713"
printf
和/bin/printf
不支持该
fc-list --format='%{postscriptname}\n' ':charset=2500-257F'
最终,gnome-terminal使用fontconfig进行(除其他事项外):
...即使已经安装了数千种字体,也可以在已安装的字体集中快速,高效地找到所需的字体...
在API文档中,您可以找到用于查询字体字符范围和用于字符范围的操作的函数,但是该文档过于神秘,以至于我始终无法弄清不同功能集之间的关系。如果我需要更深入地研究,我宁愿看一下其他软件中的用法示例,也许是vte(gnome-terminal中使用的终端仿真库)。
在vte和fontconfig之间的另一个库是pango “ ...一个用于布局和呈现文本的库,重点是国际化...”。现在我想到了,它听起来像是包含您所追求的大多数逻辑的一种。
Pango中的字符覆盖功能由覆盖图实现(“在Pango中,通常有必要确定特定字体是否可以表示特定字符,以及它可以如何很好地表示该字符。PangoCoverage是一种使用的数据结构。以表示该信息。”),但是在决定使用哪种字体呈现哪种字形时可能涉及更复杂的细节。我猜VTE依靠pango渲染具有适当字体的字符串,而pango使用fontconfig(或其他受支持的字体后端)根据pango本身和/或后端中的各种逻辑找到最合适的字体。
我更改了代码,以检查字体是否包含某个字符串的所有字符。因此,可以通过调用此方法fc-search-codepoint "$fontname" "$string"
,如果成功则返回退出代码0,否则返回1。可以从fc-query /path/to/FontSandMonoBoldOblique.ttf
或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)