Encuentre la mejor fuente para representar un punto de código

Encuentre la mejor fuente para representar un punto de código

¿Cómo encontrar la fuente adecuada para representar puntos de código Unicode?

gnome-terminalencontrar que personajes como «

Respuesta1

Usando fontconfig,

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

p.ej

> fc-list ':charset=2713 2717'

mostrará cualquier nombre de archivo de fuente que contenga ✓ y ✗.

Para obtener el punto de código correspondiente al uso del carácter (por ejemplo)

> printf "%x" \'✓
2713>

Esto utiliza uncaracterística algo oscura delprintfUtilidad POSIX:

Si el carácter inicial es una comilla simple o doble, el valor será el valor numérico en el conjunto de códigos subyacente del carácter que sigue a la comilla simple o doble.

Tomados en conjunto,

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

Esto usa la xargs -Ibandera para reemplazar {}con nombres de stdin. Entonces, esto efectivamente se reduce a:

> fc-list ":charset=2713"

Respuesta2

Este no es necesariamente el mejor método, y seguro que no es fácil de usar, pero es fácil empezar a trabajar: aquí hay un script de Python para hacerlo.

Instala elPython-fontconfigbiblioteca. Consíguelo desde tu distribución (por ejemplo, sudo apt-get install python-fontconfigen Debian y derivados) o instálalo en tu directorio de inicio ( pip install --user python-fontconfig). Luego puedes ejecutar este script (guárdalo fc-search-codepointen un directorio de tu PATH, por ejemplo, normalmente ~/bin, y hazlo ejecutable):

#!/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)

Uso de ejemplo:

$ fc-search-codepoint 

Respuesta3

En última instancia, usos de gnome-terminalconfiguración de fuentea (entre otras cosas):

...encuentre eficiente y rápidamente las fuentes que necesita entre el conjunto de fuentes que ha instalado, incluso si ha instalado miles de fuentes...

En elDocumentación APIpuedes encontrar funciones para consultar rangos de caracteres de fuentes y para operaciones en rangos de caracteres, pero la documentación es tan críptica que nunca pude entender cómo se relacionan entre sí los diferentes conjuntos de funciones. Si necesitara profundizar más, preferiría mirar ejemplos de uso en otro software, tal vezvte(la biblioteca de emulación de terminal utilizada en gnome-terminal).

Otra biblioteca en el mediovteyconfiguración de fuenteespango "...una biblioteca para maquetación y renderizado de textos, con énfasis en la internacionalización...". Ahora que lo pienso, parece que contiene la mayor parte de la lógica que buscas.

La funcionalidad de cobertura de personajes en pango se implementa mediantemapas de cobertura("A menudo es necesario en Pango determinar si una fuente en particular puede representar un carácter en particular, y también qué tan bien puede representar ese carácter. PangoCoverage es una estructura de datos que se utiliza para representar esa información".), pero probablemente haya detalles más complicados involucrados en decidir qué glifo representar con qué fuente. SupongoTEVse basa enpangopara representar cadenas con fuentes apropiadas mientraspangousosconfiguración de fuente(u otro backend de fuente compatible) para encontrar la fuente más apropiada según varios elementos de lógica enpangoen sí mismo y/o el backend.

Respuesta4

Modifiqué el código para verificar si una fuente contiene todos los caracteres de una determinada cadena. Entonces se puede llamar a esto fc-search-codepoint "$fontname" "$string"y devuelve el código de salida 0 en caso de éxito o 1 en caso contrario. Los nombres de las fuentes se pueden recuperar de fc-query /path/to/FontSandMonoBoldOblique.ttfImagemagick's convert -list font. Lo uso para verificar si una cadena seleccionada por el usuario se puede representar con la fuente seleccionada por el usuario y, si el comando falla, se usa una fuente alternativa.

#!/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)

información relacionada