如何从Linux上的TrueType或嵌入式OpenType字体中提取支持的Unicode字符列表?
是否有工具或库可用于处理.ttf或.eot文件并构建字体提供的代码点列表(如U + 0123,U + 1234等)?
答案 0 :(得分:36)
以下是使用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
答案 1 :(得分:25)
Linux程序xfd可以做到这一点。它在我的发行版中提供为xorg-xfd'。要查看字体的所有字符,可以在终端中运行:
xfd -fa "DejaVu Sans Mono"
答案 2 :(得分:12)
fc-query my-font.ttf
将根据fontconfig
由于几乎所有现代Linux应用程序都基于fontconfig,因此比原始unicode列表更有用
这里讨论实际的输出格式 http://lists.freedesktop.org/archives/fontconfig/2013-September/004915.html
答案 3 :(得分:8)
ttf / otf字体的字符代码点存储在CMAP
表中。
您可以使用ttx
生成CMAP
表的XML表示形式。见here。
您可以运行命令ttx.exe -t cmap MyFont.ttf
,它应该输出文件MyFont.ttx
。在文本编辑器中打开它,它应该显示它在字体中找到的所有字符代码。
答案 4 :(得分:7)
这是一个 POSIX [1]外壳程序脚本,它可以借助{{3}中提到的fc-match
轻松而轻松地打印代码点和字符。 }}(它甚至可以处理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标准?
答案 5 :(得分:4)
我遇到了同样的问题,并使HOWTO更进了一步,烘焙了所有受支持的Unicode代码点的正则表达式。
如果您只想要一系列代码点,则可以在运行ttx
之后偷看Chrome devtools中的ttx -t cmap myfont.ttf
xml时使用此功能,并且可能会将myfont.ttx
重命名为{{ 1}}调用Chrome的xml模式:
myfont.xml
(同样依赖于gilamesh建议中的function codepoint(node) { return Number(node.nodeValue); }
$x('//cmap/*[@platformID="0"]/*/@code').map(codepoint);
; fonttools
如果您使用的是ubuntu系统。)
答案 6 :(得分:3)
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'
检查是否匹配了正确的字体。
答案 7 :(得分:2)
要添加到@Oliver Lew 的答案中,我添加了查询本地字体而不是系统字体的选项:
#!/bin/bash
# If the first argument is a font file, use fc-match instead of fc-query to
# display the font
[[ -f "$1" ]] && fc='fc-query' || fc='fc-match'
for range in $($fc --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"
答案 8 :(得分:0)
如果您只想“查看”字体,则以下内容可能会有所帮助(如果您的终端支持相关字体):
var Twit = require ('twit');
var config = require('./config');
var T = new Twit(config);
for (var i = 0; i < tweetList.length; i++) {
var id = { id: tweetList[i].id_str }
if ('retweeted_status' in tweetList[i])
continue;
}
var message = "A lot confused, a lot does not understand feelings";
var tweetId = tweetList[i].id_str
try {
T.post('statuses/update',
{ "status": message, "in_reply_to_status_id": tweetId },
function (error, tweets, response) {
console.log("Tweet posted successfully!")
});
}
catch (err) {
console.log(err);
}
});
一种不安全但简单的查看方式:
#!/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 + "'")
感谢Janus(https://stackoverflow.com/a/19438403/431528)提供了上述答案。
答案 9 :(得分:0)
以上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毫秒。
答案 10 :(得分:0)
如果要获得字体支持的所有字符,则可以使用以下命令(基于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
答案 11 :(得分:0)
FreeType的项目提供了演示应用程序,其中的一个演示称为“ ftdump”。然后,您可以执行以下操作:“ ftdump -V指向字体文件的路径”,您将获得所需的内容。要查看源代码,可以在此处关闭源代码:https://www.freetype.org/developer.html
在Ubuntu上,可以使用“ sudo apt install freetype2-demos”进行安装
注意:尝试使用“ -c”而不是“ -V”。我看到版本之间的args有所更改。
答案 12 :(得分:-1)
您可以使用Font::TTF模块在Perl的Linux上执行此操作。