如何在Linux上从TrueType或嵌入式OpenType字体中提取受支持的Unicode字符列表?
我是否可以使用工具或库来处理.ttf或.eot文件并构建字体提供的代码点列表(如U + 0123,U + 1234等)?
Answers:
这是使用FontTools模块的方法(可以使用来安装pip install fonttools
):
#!/usr/bin/env python
from itertools import chain
import sys
from fontTools.ttLib import TTFont
from fontTools.unicode import Unicode
ttf = TTFont(sys.argv[1], 0, verbose=0, allowVID=0,
ignoreDecompileErrors=True,
fontNumber=-1)
chars = chain.from_iterable([y + (Unicode[y[0]],) for y in x.cmap.items()] for x in ttf["cmap"].tables)
print(list(chars))
# Use this for just checking if the font contains the codepoint given as
# second argument:
#char = int(sys.argv[2], 0)
#print(Unicode[char])
#print(char in (x[0] for x in chars))
ttf.close()
该脚本将字体路径作为参数:
python checkfont.py /path/to/font.ttf
int(sys.argv[2], 0)
在大多数情况下,它将以“无效文字”失败,因为人们可能想查找特殊字符。使用ord(sys.argv[2].decode('string_escape').decode('utf-8'))
代替。
python-fontconfig
速度似乎要快得多:unix.stackexchange.com/a/268286/26952
sys.argv[1]
给TTFont()
?
chars = chain.from_iterable([y + (Unicode[y[0]],) for y in x.cmap.items()] for x in ttf["cmap"].tables)
作者chars = list(y + (Unicode[y[0]],) for x in ttf["cmap"].tables for y in x.cmap.items())
X程序xfd可以执行此操作。要查看“ DejaVu Sans Mono”字体的所有字符,请运行:
xfd -fa "DejaVu Sans Mono"
它包含在Debian / Ubuntu的x11-utils软件包,Fedora / RHEL的xorg-x11-apps和Arch Linux的xorg-xfd中。
6x13
?
fc-query my-font.ttf
将为您提供支持的字形的地图以及该字体适合的所有语言环境(根据fontconfig
由于几乎所有现代linux应用程序都是基于fontconfig的,因此它比原始unicode列表有用得多
此处讨论了实际的输出格式 http://lists.freedesktop.org/archives/fontconfig/2013-September/004915.html
这些fontconfig
命令可以将字形列表输出为范围的紧凑列表,例如:
$ fc-match --format='%{charset}\n' OpenSans
20-7e a0-17f 192 1a0-1a1 1af-1b0 1f0 1fa-1ff 218-21b 237 2bc 2c6-2c7 2c9
2d8-2dd 2f3 300-301 303 309 30f 323 384-38a 38c 38e-3a1 3a3-3ce 3d1-3d2 3d6
400-486 488-513 1e00-1e01 1e3e-1e3f 1e80-1e85 1ea0-1ef9 1f4d 2000-200b
2013-2015 2017-201e 2020-2022 2026 2030 2032-2033 2039-203a 203c 2044 2070
2074-2079 207f 20a3-20a4 20a7 20ab-20ac 2105 2113 2116 2120 2122 2126 212e
215b-215e 2202 2206 220f 2211-2212 221a 221e 222b 2248 2260 2264-2265 25ca
fb00-fb04 feff fffc-fffd
使用fc-query
的.ttf
文件和fc-match
已安装的字体名称。
这可能不涉及安装任何额外的软件包,也不涉及翻译位图。
使用fc-match --format='%{file}\n'
检查正确的字体是否被匹配。
ttx -t cmap -o - /usr/share/fonts/truetype/GentiumPlus-I.ttf | grep 0x2161
回报<map code="0x2161" name="uni2161"/><!-- ROMAN NUMERAL TWO -->
。FontConfig可能与其他字体匹配。在我安装之前gentium
,fc-match 'Gentium Italic'
退货了FreeMono.ttf: "FreeMono" "Regular"
。如果是这样,的输出--format=%{charset}
将不会显示您的期望。
fc-match --format='%{file} ⇒ %{charset}\n' Gentium:Italic
n'Gentium :斜体/usr/share/fonts/truetype/gentium/Gentium-I.ttf和DTRT,太好了。
Gentium:Italic
而不是Gentium Italic
。感谢那。
这是一个POSIX [1] shell脚本,可以fc-match
在Neil Mayhew的答案中提到(它甚至可以处理最多8个十六进制的Unicode),以一种很好的方式轻松地打印代码点和字符。
#!/bin/sh
for range in $(fc-match --format='%{charset}\n' "$1"); do
for n in $(seq "0x${range%-*}" "0x${range#*-}"); do
n_hex=$(printf "%04x" "$n")
# using \U for 5-hex-digits
printf "%-5s\U$n_hex\t" "$n_hex"
count=$((count + 1))
if [ $((count % 10)) = 0 ]; then
printf "\n"
fi
done
done
printf "\n"
您可以传递字体名称或任何fc-match
可接受的名称:
$ ls-chars "DejaVu Sans"
更新内容:
我了解到子外壳非常耗时(printf
脚本中的子外壳)。因此,我设法编写了一个改进的版本,速度提高了5到10倍!
#!/bin/sh
for range in $(fc-match --format='%{charset}\n' "$1"); do
for n in $(seq "0x${range%-*}" "0x${range#*-}"); do
printf "%04x\n" "$n"
done
done | while read -r n_hex; do
count=$((count + 1))
printf "%-5s\U$n_hex\t" "$n_hex"
[ $((count % 10)) = 0 ] && printf "\n"
done
printf "\n"
旧版本:
$ time ls-chars "DejaVu Sans" | wc
592 11269 52740
real 0m2.876s
user 0m2.203s
sys 0m0.888s
新版本(行号指示5910个字符,在0.4秒内!):
$ time ls-chars "DejaVu Sans" | wc
592 11269 52740
real 0m0.399s
user 0m0.446s
sys 0m0.120s
更新结束
样本输出(它在我的st端子better中排列得更好):
0020 0021 ! 0022 " 0023 # 0024 $ 0025 % 0026 & 0027 ' 0028 ( 0029 )
002a * 002b + 002c , 002d - 002e . 002f / 0030 0 0031 1 0032 2 0033 3
0034 4 0035 5 0036 6 0037 7 0038 8 0039 9 003a : 003b ; 003c < 003d =
003e > 003f ? 0040 @ 0041 A 0042 B 0043 C 0044 D 0045 E 0046 F 0047 G
...
1f61a😚 1f61b😛 1f61c😜 1f61d😝 1f61e😞 1f61f😟 1f620😠 1f621😡 1f622😢 1f623😣
1f625😥 1f626😦 1f627😧 1f628😨 1f629😩 1f62a😪 1f62b😫 1f62d😭 1f62e😮 1f62f😯
1f630😰 1f631😱 1f632😲 1f633😳 1f634😴 1f635😵 1f636😶 1f637😷 1f638😸 1f639😹
1f63a😺 1f63b😻 1f63c😼 1f63d😽 1f63e😾 1f63f😿 1f640🙀 1f643🙃
[1]似乎\U
在printf
不POSIX标准?
我有同样的问题,并提出了HOWTO是更进了一步,烘烤所有支持Unicode代码点的正则表达式。
如果你只是想码点的阵列,你可以在你偷看时使用ttx
的镀铬devtools XML,运行后ttx -t cmap myfont.ttf
和可能,重新命名myfont.ttx
,以myfont.xml
调用浏览器的XML模式:
function codepoint(node) { return Number(node.nodeValue); }
$x('//cmap/*[@platformID="0"]/*/@code').map(codepoint);
(如果您使用的是ubuntu系统fonttools
,也请参考gilamesh的建议sudo apt-get install fonttools
。)
上面Janus的答案(https://stackoverflow.com/a/19438403/431528)起作用。但是python太慢了,特别是对于亚洲字体。在E5计算机上,文件大小为40MB的字体花费几分钟。
所以我写了一个C ++程序来做到这一点。它取决于FreeType2(https://www.freetype.org/)。这是一个vs2015项目,但由于它是一个控制台应用程序,因此很容易移植到linux。
可以在这里找到代码,https://github.com/zhk/AllCodePoints 对于40MB文件大小的亚洲字体,在我的E5计算机上花费大约30毫秒。
如果您只想“查看”字体,则以下内容可能会有所帮助(如果您的终端支持相关字体):
#!/usr/bin/env python
import sys
from fontTools.ttLib import TTFont
with TTFont(sys.argv[1], 0, ignoreDecompileErrors=True) as ttf:
for x in ttf["cmap"].tables:
for (_, code) in x.cmap.items():
point = code.replace('uni', '\\u').lower()
print("echo -e '" + point + "'")
一种不安全但简单的查看方式:
python font.py my-font.ttf | sh
感谢Janus(https://stackoverflow.com/a/19438403/431528)提供了上述答案。
如果要获得字体支持的所有字符,则可以使用以下命令(基于Janus的回答)
from fontTools.ttLib import TTFont
def get_font_characters(font_path):
with TTFont(font_path) as font:
characters = {chr(y[0]) for x in font["cmap"].tables for y in x.cmap.items()}
return characters
FreeType的项目提供了演示应用程序,其中的一个演示称为“ ftdump”。然后,您可以执行以下操作:“ ftdump -V指向字体文件的路径”,您将获得所需的内容。要查看源代码,可以在此处关闭源代码:https : //www.freetype.org/developer.html
在Ubuntu上,可以使用“ sudo apt install freetype2-demos”进行安装。
注意:尝试使用“ -c”而不是“ -V”。我看到args在版本之间已更改。
fc-list :charset=1234
,但仔细检查它的输出...(它确实对我