11 votos

Obtener la lista de todas las fuentes que contienen un carácter específico

En MacOS Sierra, me gustaría obtener una lista utilizable de todas las fuentes que cubren (contienen un glifo para) un carácter Unicode particular. Hay alguna manera de hacerlo, ya sea a través de una herramienta, o de la línea de comandos, o escribiendo un programa?

Ahora mismo, esto es lo que puedo hacer:

  1. En Preferencias del Sistema Teclado, hay una opción para "Mostrar los visores de teclado y emoji en la barra de menú" show keyboard que he activado. Esto habilita un menú en la esquina superior derecha de la pantalla, junto a la hora y la fecha.
  2. En ese menú, elijo "Mostrar emoji y símbolos" (que creo que antes se llamaba "Visor de caracteres"):

Show Emoji and symbols

  1. Aquí puedo buscar el carácter y en "Variación de fuentes" puedo hacer clic en cada representación y ver la fuente correspondiente:

Font variation

Esto es utilizable cuando hay suficientes fuentes que contienen el carácter, pero es poco manejable (requiere muchos clics y copias) cuando la lista de fuentes es grande. Lo que me gustaría es obtener una lista de todos esos tipos de letra en forma de texto plano copiable.

¿Cómo puedo hacerlo? Estoy dispuesto y feliz de escribir código si es necesario.

9voto

tonyk Puntos 56

Todavía no me queda claro cómo lo hace el propio MacOS, pero mientras tanto esto es lo que terminé haciendo.

Las soluciones que encontré eran todas de la siguiente forma:

  1. Obtenga una lista de todas las fuentes disponibles.
  2. Recorre la lista para encontrar las fuentes que contienen el carácter seleccionado.

Listado de todas las fuentes

A partir de esta pregunta Hay dos enfoques (más un tercero que encontré) aquí ):

  1. system_profiler SPFontsDataType al que se puede añadir -xml para obtener la salida en XML,

  2. fc-list que puede tomar un patrón ( : es el patrón vacío que coincide con todas las fuentes) y un especificador de formato.

  3. Al instante python-fontconfig y, a continuación, ejecute import fontconfig; fontconfig.query() para obtener una lista de rutas de fuentes.

La comparación de los dos enfoques (escribí esto antes de haberme fijado en el tercero) es interesante:

  • La velocidad: En mi ordenador y para mi conjunto de fuentes, fc-list tarda unos 24 segundos la primera vez y 0,04 segundos cada vez después, mientras que system_profiler tarda sistemáticamente unos 3 segundos cada vez.

  • Amplitud: En mi sistema actual, system_profiler tiene una lista de 702 fuentes, mientras que fc-list listas 770: todos esos 702 más 68 más. Por un lado, system_profiler parece ser la forma "oficial", y coincide con las fuentes visibles en el Libro de fuentes, las que aparecen en "Variación de fuentes" en el visor de caracteres/símbolos (como en la pregunta), el menú en TextEdit, etc. Por otro lado, al menos algunas de las fuentes que se pierden son fuentes realmente utilizables. Esto incluye no sólo las 5 fuentes /Library/Fonts/{Athelas.ttc,Charter.ttc,Marion.ttc,Seravek.ttc,SuperClarendon.ttc} sobre el que se pueden encontrar algunas páginas confusas en Internet (por ejemplo este y este ), pero también /Library/Fonts/{DIN Alternate Bold.ttf,DIN Condensed Bold.ttf,Iowan Old Style.ttc} y 57 de los 177 Noto Sans fuentes que tengo instaladas en mi sistema. Por ejemplo, tengo instalada la Noto Sans Brahmi, pero esta fuente no aparece en el Libro de fuentes ni en "Variación de fuentes" cuando busco una letra Brahmi (digamos ), pero sí se utiliza en TextEdit (y se muestra en mi navegador). Sea cual sea la razón de esta rareza, estoy contento de poder obtener la lista completa con fc-list .

  • Facilidad de uso: con cualquiera de los dos métodos se requiere un poco de análisis de la salida. Con fc-list Puedo especificar el formato (por ejemplo fc-list --format="%{family}\n%{file}\n%{lang}\n\n" pero no pude encontrar una referencia para los nombres de los campos); con system_profiler Puedo simplemente grep para Location: o la salida a XML y parsear el XML (ejemplos con xml.etree.ElementTree , con plistlib ).

¿Este tipo de letra cubre este carácter?

Sea como sea que obtengamos la lista de fuentes, a continuación tenemos que comprobar si un carácter está cubierto por una fuente específica (dada por el nombre o la ruta). De nuevo, las formas que he encontrado:

  • Utilice uno de los enlaces de FreeType . En el caso de Python, existe freetype-py pero no he podido averiguar en pocos minutos cómo utilizarlo.

  • Volcar la tabla cmap de la fuente con ttx/fonttools , y luego hacer un bucle sobre la tabla. Esto es ciertamente factible y he utilizado este tipo de dumping muchas veces (uno puede simplemente ttx foo.ttf para obtener el foo.ttx xml que es incluso legible para los humanos), pero para este caso de uso (buscar en todas las fuentes), no es lo mejor, ya que tarda segundos por fuente.

  • Busca la tabla cmap en una biblioteca escrita para ello: use Font::TTF::Font en Perl , from fontTools.ttLib import TTFont en Python -- esto sería algo así como:

    def has_char(font_path, c):
        """Does font at `font_path` contain the character `c`?"""
        from fontTools.ttLib import TTFont
        from fontTools.unicode import Unicode
        try:
            font = TTFont(font_path)
            for table in font['cmap'].tables:
                for char_code, glyph_name in table.cmap.items():
                    if char_code == ord(c):
                        font.close()
                        return True
        except Exception as e:
            print('Error while looking at font %s: %s' % (font_path, e))
            pass
        return False

    Por desgracia, falla en demasiadas fuentes para ser útil.

  • Si utiliza la solución Python-fontconfig Hay un has_char usado como..: font = fontconfig.FcFont(path); return font.has_char(c)

Resumen

Acabé utilizando la solución de aquí que he reescrito ligeramente para que sea mínimo:

#!/usr/bin/env python

def find_fonts(c):
    """Finds fonts containing  the (Unicode) character c."""
    import fontconfig
    fonts = fontconfig.query()
    for path in sorted(fonts):
        font = fontconfig.FcFont(path)
        if font.has_char(c):
            yield path

if __name__ == '__main__':
    import sys
    search = sys.argv[1]
    char = search.decode('utf-8') if isinstance(search, bytes) else search
    for path in find_fonts(char):
        print(path)

Ejemplo de uso:

% python3 find_fonts.py ''
/Library/Fonts/Arial Unicode.ttf
/Library/Fonts/Kannada MN.ttc
/Library/Fonts/Kannada MN.ttc
/Library/Fonts/Kannada Sangam MN.ttc
/Library/Fonts/Kannada Sangam MN.ttc
/System/Library/Fonts/LastResort.ttf
/Users/shreevatsa/Library/Fonts/Kedage-b.TTF
/Users/shreevatsa/Library/Fonts/Kedage-i.TTF
/Users/shreevatsa/Library/Fonts/Kedage-n.TTF
/Users/shreevatsa/Library/Fonts/Kedage-t.TTF
/Users/shreevatsa/Library/Fonts/NotoSansKannada-Bold.ttf
/Users/shreevatsa/Library/Fonts/NotoSansKannada-Regular.ttf
/Users/shreevatsa/Library/Fonts/NotoSansKannadaUI-Bold.ttf
/Users/shreevatsa/Library/Fonts/NotoSansKannadaUI-Regular.ttf
/Users/shreevatsa/Library/Fonts/NotoSerifKannada-Bold.ttf
/Users/shreevatsa/Library/Fonts/NotoSerifKannada-Regular.ttf
/Users/shreevatsa/Library/Fonts/akshar.ttf

(Funciona tanto con python3 y python2 , cualquiera que sea python que tienes. Tarda unos 29 segundos en mi ordenador, para el conjunto de fuentes que tengo instaladas).

AppleAyuda.com

AppleAyuda es una comunidad de usuarios de los productos de Apple en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X