코드 포인트 렌더링에 가장 적합한 글꼴 찾기


16

유니 코드 코드 포인트 렌더링에 적합한 글꼴을 찾는 방법은 무엇입니까?

gnome-terminal«🉃 ⼼ 😻🕲🝤»와 같은 문자는 내 터미널 글꼴이나 코드 포인트 인 스퀘어 폴백 (????) 대신 Symbola와 같은 글꼴로 렌더링 될 수 있습니다. 어떻게 ?


답변:


14

이것이 반드시 최선의 방법은 아니지만 사용자에게 친숙하지는 않지만 작업하기 쉽습니다. 여기에 파이썬 스크립트가 있습니다.

Python-fontconfig 라이브러리를 설치하십시오 . 배포본 (예 : sudo apt-get install python-fontconfig데비안 및 파생 제품)에서 가져 오거나 홈 디렉토리에 설치하십시오 ( 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 python를 바꾸시겠습니까?#!/usr/bin/env python2
Zulan

1
이 답변에 감사드립니다! 매우 도움이되었습니다. 글꼴 대체를 구현하는 OS 또는 시스템 라이브러리가 더 효율적인 작업을 수행하고 있다고 확신하지만 작동합니다. @Zulan 그것은 또한 작동하도록 만들 수 있습니다 python3; 방금 이 답변 의 맨 아래에 더 작은 버전을 썼습니다 .
ShreevatsaR

5

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"

2
참고로이 버전을 필요 fontconfig2.11.91또는 나중에 .
Nathaniel M. Beaver

1
대시 printf/bin/printf그것을 지원하지 않습니다
Steven Penny

1
대박! 나는 이것에 대한 정보를 오랫동안 찾고있다. 단일 문자뿐만 아니라 범위도 지정할 수 있으므로 상자 그리기 문자가 모두있는 모든 글꼴을 찾을 수 있습니다.fc-list --format='%{postscriptname}\n' ':charset=2500-257F'
Neil Mayhew

3

궁극적으로 그놈 터미널은 fontconfig 를 사용 하여 다음과 같은 작업을 수행합니다.

... 수천 개의 글꼴을 설치 한 경우에도 설치 한 글꼴 세트 중 필요한 글꼴을 효과적이고 빠르게 찾을 수 있습니다.

에서 API 문서 는 쿼리 글꼴 문자 범위와 문자 범위에 작업 기능을 찾을 수 있지만, 문서 기능의 다른 세트는 서로 어떤 관계가 어떻게 알아낼 수 없었다 결코 너무 비밀이다. 더 깊이 들어가야 한다면 다른 소프트웨어, vte (그놈 터미널에서 사용되는 터미널 에뮬레이션 라이브러리) 의 사용법 예를 보려고 합니다.

vtefontconfig 사이의 또 다른 라이브러리 는 pango "... 국제화에 중점을 둔 텍스트 레이아웃 및 렌더링을위한 라이브러리 ..." 입니다. 내가 생각하기에, 그것은 당신이 따르는 논리의 대부분을 포함하는 것으로 들립니다.

pango의 문자 적용 범위 기능은 적용 범위 맵에 의해 구현됩니다 ( "특정 글꼴이 특정 문자를 나타낼 수 있는지 여부와 해당 문자를 얼마나 잘 표현할 수 있는지를 결정하기 위해 Pango에서 종종 필요합니다. PangoCoverage는 사용되는 데이터 구조입니다. ". 그 정보를 표현하기 ),하지만 글꼴을 렌더링하기 위해 문자 모양 어떤 결정에 관련된 더 복잡한 세부 사항은 아마이 있습니다. 나는 생각 VTE가 에 의존 pango와 동안 적절한 글꼴로 문자열을 렌더링하기 위해 pango와의 용도 는 fontconfig (또는 다른 지원되는 글꼴 백엔드)에서 논리의 재현 다양한에 따라 가장 적절한 글꼴을 찾을 pango와 자체 및 / 또는 백엔드.


1

글꼴에 특정 문자열의 모든 문자가 포함되어 있는지 확인하기 위해 코드를 변경했습니다. 따라서 호출 할 수 있으며 fc-search-codepoint "$fontname" "$string"성공하면 종료 코드 0을 반환하고 그렇지 않으면 1을 반환합니다. 글꼴 이름은 fc-query /path/to/FontSandMonoBoldOblique.ttf또는 Imagemagick 's 에서 검색 할 수 있습니다 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.