Kod noktası oluşturmak için en iyi yazı tipini bulma


16

Unicode kod noktalarını oluşturmak için uygun yazı tipi nasıl bulunur?

gnome-terminal«🉃 ⼼ 😻🕲🝤» gibi karakterlerin uçbirim yazı tipim veya kare kod geri dönüşü (????) yerine Symbola gibi yazı tipleriyle oluşturulabileceğini bulun. Nasıl ?


Yanıtlar:


14

Bu mutlaka en iyi yöntem değildir ve kesinlikle kullanıcı dostu değildir, ancak çalışmak kolaydır: İşte bunu yapmak için bir Python betiği.

Python-fontconfig kitaplığını yükleyin . Ya dağıtımınızdan (örn sudo apt-get install python-fontconfig. Debian ve türevleri üzerinde) alın ya da ana dizininize yükleyin ( pip install --user python-fontconfig). Sonra bu komut dosyasını çalıştırabilirsiniz ( örneğin, tipik olarak ve genellikle yürütülebilir fc-search-codepointbir dizinde olduğu gibi ):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)

Örnek kullanım:

$ fc-search-codepoint 🉃⼼😻🕲🝤
$ echo $?
1

Tüm bu karakterleri içeren yazı tipim yok.

$ fc-search-codepoint U+1F64D
/usr/share/fonts/truetype/unifont/unifont_upper.ttf
/usr/share/fonts/truetype/unifont/unifont_upper_csur.ttf

1
Bu çok yararlı bir senaryo! Ancak, sadece python2 uyumlu ve tam olarak bu taşınabilir yapmak için biraz kötü olduğunu varsayalım. Eğer değişen en az sorun olur #!/usr/bin/env pythonüzere #!/usr/bin/env python2olduğu PEP başına 394.
Zulan

1
Bu cevap için teşekkürler! Çok yardımcı oldu. Eminim font yedeklemeyi uygulayan işletim sistemi veya sistem kitaplıkları daha verimli bir şey yapıyor, ancak bu çalışıyor. @Zulan ile çalışmak python3da yapılabilir; Bu cevabın altına bunun daha küçük bir versiyonunu yazdım .
ShreevatsaR

5

Fontconfig kullanarak,

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

Örneğin

> fc-list ':charset=2713 2717'

✓ ve ✗ içeren yazı tipi dosya adlarını görüntüler.

Kod değerinin karakter kullanımına karşılık gelmesini sağlamak için (örneğin)

> printf "%x" \'✓
2713>

Bu kullanan bir şekilde karanlık özelliği arasında POSIX printfprogramı :

Baştaki karakter tek tırnak veya çift tırnak ise, değer tek tırnak veya çift tırnaktan sonraki karakterin temel kod kümesindeki sayısal değer olmalıdır.

Birlikte alındıklarında,

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

Bu, adını adlarıyla xargs -Ideğiştirmek için bayrağı kullanır . Böylece bu etkili bir şekilde kaybolur:{}stdin

> fc-list ":charset=2713"

2
Not ait bir sürümünü gerektiğini fontconfigolmasıdır 2.11.91veya sonradan .
Nathaniel M. Beaver

1
dikkat edin printfve /bin/printfbunu desteklemeyin
Steven Penny

1
Müthiş! Uzun zamandır bu konuda bilgi arıyordum. Tüm kutu çizim karakterlerine sahip tüm yazı tiplerini bulmak için aralıkları ve tek karakterleri de belirtebileceğinizi unutmayın, örneğin:fc-list --format='%{postscriptname}\n' ':charset=2500-257F'
Neil Mayhew

3

Sonuçta gnome-terminal (diğer şeylerin yanı sıra) için fontconfig kullanır :

... binlerce yazı tipi kurmuş olsanız bile, yüklediğiniz yazı tipleri arasında ihtiyacınız olan yazı tiplerini verimli ve hızlı bir şekilde bulun ...

In API belgelerine sorgu yazı karakteri aralıklarına ve karakter aralıkları işlemleri için fonksiyonlar bulabilirsiniz, ancak dokümantasyon fonksiyonları farklı setleri birbirleriyle ilişkisini nasıl hiç anlayamamıştı o kadar gizlenmiştir. Daha derinlemesine dalmam gerekirse , belki de vte (gnome-terminalinde kullanılan terminal öykünme kütüphanesi ) gibi diğer yazılımlardaki kullanım örneklerine bakmayı tercih ederim .

Arasındaki bir diğer kütüphane VTE ve fontconfig olan pango "... ... uluslararası bir vurgu ile, dışarı atarken ve metnin oluşturma için bir kütüphane" . Şimdi düşündüğüme göre, peşinde olduğunuz mantığın çoğunu içeren bir ses gibi görünüyor.

Pango'daki karakter kapsamı işlevselliği kapsam haritaları tarafından uygulanır ( "Pango'da belirli bir yazı tipinin belirli bir karakteri temsil edip edemeyeceğini ve o karakteri ne kadar iyi temsil edebileceğini belirlemek genellikle PangoCoverage kullanılır. " ), ancak hangi glifin hangi yazı tipi ile oluşturulacağına muhtemelen daha karmaşık ayrıntılar dahildir. Sanırım VTE dayanır pango ederken uygun yazı tipleri ile dizeleri işlemek için pango kullandığı fontconfig (veya desteklenen diğer yazı yönetim) mantığın parçalı çeşitli dayalı en uygun yazı tipini bulmak için pango kendisi ve / veya arka uç.


1

Bir yazı tipinin belirli bir dizenin tüm karakterlerini içerip içermediğini kontrol etmek için kodu değiştirdim. Böylece bu çağrılabilir fc-search-codepoint "$fontname" "$string"ve başarılı olduğunda çıkış kodunu 0 veya aksi takdirde 1 değerini döndürür. Yazı tipi adları fc-query /path/to/FontSandMonoBoldOblique.ttfveya Imagemagick'ten alınabilir convert -list font. Ben kullanıcı tarafından seçilen bir dize kullanıcı tarafından seçilen yazı tipi ile render edilebilir olup olmadığını kontrol etmek için kullanın ve komut başarısız olursa, bir yedek yazı tipi kullanılır.

#!/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)
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.