コードポイントのレンダリングに最適なフォントを見つける


16

Unicodeコードポイントをレンダリングするための適切なフォントを見つける方法

gnome-terminal«🉃⼼😻🕲🝤»のような文字は、私の端末フォントやcodepoint-in-squareフォールバック(????)ではなく、Symbolaなどのフォントでレンダリングできることがわかります。どうやって ?


回答:


14

これは必ずしも最良の方法ではなく、ユーザーフレンドリーではないことは確かですが、簡単に作業を開始できます。これを実行するPythonスクリプトを次に示します。

Python-fontconfigライブラリをインストールします。ディストリビューションから取得するか(例:sudo apt-get install python-fontconfigDebianおよび派生物)、またはホームディレクトリにインストールします(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

1
これは非常に役立つスクリプトです!しかし、それはpython2に準拠しているだけであり、まさにその移植性を実現するのは少し厄介だと思います。少なくともPEP 394に従って#!/usr/bin/env pythonto #!/usr/bin/env python2を変更してもらえますか?
ズラン

1
この答えをありがとう!とても助かりました。フォントフォールバックを実装するOSまたはシステムライブラリはより効率的なことを行っていると確信していますが、これは機能します。@Zulan一緒に動作させることもできpython3ます。この答えの下部にこれの小さいバージョンを書いたところです。
シュリーバツァー

5

fontconfigを使用して、

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

例えば

> fc-list ':charset=2713 2717'

✓およびcontainingを含むフォントファイル名が表示されます。

文字の使用に対応するコードポイントを取得するには(たとえば)

> printf "%x" \'✓
2713>

これは 、POSIX ユーティリティのややあいまいな機能を使用しますprintf

先行文字が単一引用符または二重引用符である場合、値は、単一引用符または二重引用符に続く文字の基になるコードセットの数値でなければなりません。

まとめて、

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

これは、xargs -Iフラグを使用して{}からの名前に置き換えますstdin。したがって、これは実質的に次のように要約されます。

> fc-list ":charset=2713"

2
あなたがのバージョン必要があることに注意fontconfigそれがある2.11.91、後で
ナサニエルM.ビーバー

1
ダッシュprintf/bin/printfサポートしてはいけないことに注意してください
スティーブンペニー

1
驚くばかり!私はこれに関する情報を長い間探していました。あなたもそう例えば、すべてのボックス描画文字を持っているすべてのフォントを見つけるために、範囲ならびに単一の文字を指定できることに注意してください:fc-list --format='%{postscriptname}\n' ':charset=2500-257F'
ニール・メイヒュー

3

最終的に、gnome-terminalは(とりわけ)fontconfigを使用します。

...何千ものフォントをインストールした場合でも、インストールしたフォントのセットの中から必要なフォントを効率的かつ迅速に見つけます...

ではAPIドキュメントクエリフォントの文字範囲に、文字の範囲で操作するための関数を見つけることができますが、ドキュメントには、機能の異なるセットが互いにどのように関係するかを私は把握できなかっ決してほど不可解です。さらに深く掘り下げる必要がある場合は、他のソフトウェア、おそらくvte(gnome-terminalで使用されるターミナルエミュレーションライブラリ)の使用例を見てみたいと思います。

vtefontconfigの間のもう1つのライブラリはpango "...国際化に重点を置いた、テキストのレイアウトとレンダリングのためのライブラリ..."です。今考えてみると、それはあなたが求めているロジックのほとんどを含むもののように聞こえます。

pangoのキャラクターカバレッジ機能は、カバレッジマップによって実装されます「Pangoでは、特定のフォントが特定のキャラクターを表すことができるかどうか、またそのキャラクターをどれだけうまく表現できるかを判断する必要があります。PangoCoverageは、使用されるデータ構造その情報を表現するために」。私は推測VTEはに依存しているPangoの間、適切なフォントで文字列をレンダリングするためのPangoの使用はfontconfig(またはその他のサポートフォントのバックエンドは)のロジックのつなぎ様々に基づいて、最も適切なフォントを見つけるためにはPango自体および/またはバックエンドを。


1

フォントを特定の文字列のすべての文字が含まれているかどうかを確認するコードを変更しました。そのため、これを呼び出すことができ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)
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.