11 votes

Obtenir la liste de toutes les polices contenant un caractère spécifique

Sur MacOS Sierra, j'aimerais obtenir une liste utilisable de toutes les polices qui couvrent (contiennent un glyphe pour) un caractère Unicode particulier. Existe-t-il un moyen de le faire, soit via un outil, soit via la ligne de commande, soit en écrivant un programme ?

Pour l'instant, c'est ce que je peux faire :

  1. Sous Préférences système - Clavier, il y a une option pour "Afficher les visualisations du clavier et des emoji dans la barre de menu". show keyboard que j'ai activé. Cela active un menu dans le coin supérieur droit de l'écran, à côté de l'heure et de la date.
  2. Dans ce menu, je choisis "Show Emoji and Symbols" (qui, je crois, était auparavant appelé "Character Viewer") :

Show Emoji and symbols

  1. Ici, je peux rechercher le caractère et sous "Variation de la police", je peux cliquer sur chaque rendu et voir la police correspondante :

Font variation

Cette méthode est utilisable lorsqu'il y a suffisamment peu de polices contenant le caractère, mais elle est peu maniable (elle nécessite beaucoup de clics et de copies) lorsque la liste des polices est importante. Ce que j'aimerais, c'est obtenir une liste de toutes ces polices sous une forme copiable en texte clair.

Comment puis-je faire ça ? Je suis prêt et heureux d'écrire du code si nécessaire.

9voto

Vitaly Sharovatov Points 400

Je ne sais toujours pas comment MacOS procède, mais en attendant, voici ce que j'ai fini par faire.

Les solutions que j'ai trouvées étaient toutes de la forme suivante :

  1. Obtenez une liste de toutes les polices disponibles.
  2. Boucle sur la liste pour trouver les polices qui contiennent le caractère sélectionné.

Liste de toutes les polices

En date du cette question Il existe deux approches (plus une troisième que j'ai trouvée). ici ) :

  1. system_profiler SPFontsDataType à laquelle vous pouvez ajouter -xml pour obtenir une sortie en XML,

  2. fc-list qui peut prendre un motif ( : est le motif vide qui correspond à toutes les polices) et un spécificateur de format.

  3. Instantanément python-fontconfig puis exécutez import fontconfig; fontconfig.query() pour obtenir une liste de chemins de polices.

La comparaison des deux approches (j'ai écrit ceci avant d'avoir remarqué la troisième) est intéressante :

  • Vitesse : Sur mon ordinateur et pour mon jeu de polices, fc-list prend environ 24 secondes la première fois et 0,04 seconde chaque fois après cela, tandis que system_profiler prend systématiquement environ 3 secondes à chaque fois.

  • L'exhaustivité : Sur mon système actuel, system_profiler énumère 702 polices de caractères, tandis que fc-list listes 770 : toutes ces 702 plus 68 autres. D'un côté, system_profiler semble être la méthode "officielle", et correspond aux polices visibles dans le Livre des polices, celles qui apparaissent dans "Variation des polices" dans le visualiseur de caractères/symboles (comme dans la question), le menu dans TextEdit, etc. D'un autre côté, au moins certaines des polices qui lui manquent sont des polices réellement utilisables. Cela inclut non seulement les 5 polices /Library/Fonts/{Athelas.ttc,Charter.ttc,Marion.ttc,Seravek.ttc,SuperClarendon.ttc} à propos duquel vous pouvez trouver quelques pages confuses en ligne (par ex. ce y ce ), mais aussi /Library/Fonts/{DIN Alternate Bold.ttf,DIN Condensed Bold.ttf,Iowan Old Style.ttc} et 57 des 177 Noto Sans les polices que j'ai installées sur mon système. Par exemple, j'ai installé Noto Sans Brahmi, mais cette police n'apparaît pas dans Font Book ou dans "Font Variation" lorsque je recherche une lettre Brahmi (disons ), mais elle est utilisée dans TextEdit (et affichée dans mon navigateur). Quelle que soit la raison de cette bizarrerie, je suis content de pouvoir obtenir la liste complète avec fc-list .

  • Facilité d'utilisation : avec l'une ou l'autre des méthodes, il est nécessaire d'analyser un peu la sortie. Avec fc-list Je peux spécifier le format (par ex. fc-list --format="%{family}\n%{file}\n%{lang}\n\n" mais je n'ai pas trouvé de référence pour les noms des champs !); avec system_profiler Je peux soit juste chercher Location: ou sortie en XML et analyse du XML (exemples avec xml.etree.ElementTree , avec plistlib ).

Cette police couvre-t-elle ce personnage ?

Quelle que soit la façon dont nous obtenons la liste des polices, nous devons ensuite vérifier si un caractère est couvert par une police spécifique (donnée par son nom ou son chemin). Encore une fois, les moyens que j'ai trouvés :

  • Utilisez l'une des liaisons FreeType . Pour Python, il existe freetype-py mais je n'ai pas réussi à comprendre en quelques minutes comment l'utiliser.

  • Vide la table cmap de la police avec ttx/fonttools puis boucle sur la table. C'est certainement faisable et j'ai utilisé ce type de vidage à plusieurs reprises (on peut juste ttx foo.ttf pour obtenir le foo.ttx xml qui est même lisible par l'homme), mais pour ce cas d'utilisation (recherche sur toutes les polices), ce n'est pas le meilleur car cela prend des secondes par police.

  • Recherchez la table cmap dans une bibliothèque écrite à cet effet : use Font::TTF::Font en Perl , from fontTools.ttLib import TTFont en Python -- ce serait quelque chose comme :

    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

    Malheureusement, il échoue sur beaucoup trop de polices pour être utile.

  • Si vous utilisez la solution Python-fontconfig il y a un has_char utilisé comme : font = fontconfig.FcFont(path); return font.has_char(c)

Résumé

J'ai fini par utiliser la solution de ici que j'ai légèrement réécrite pour la rendre minimale :

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

Exemple d'utilisation :

% 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

(Fonctionne avec les deux python3 y python2 , quel que soit python vous avez. Cela prend environ 29 secondes sur mon ordinateur, pour le jeu de polices que j'ai installé).

1voto

Vous pouvez utiliser l'outil en ligne de commande albatross ( https://gitlab.com/islandoftex/albatross/ ; également inclus dans les distributions tex comme texlive ou miktex).

Si vous exécutez albatross vous obtiendrez une liste de toutes vos polices qui contiennent le caractère :

.---.-.|  |  |--.---.-.|  |_.----.-----.-----.-----.
|  _  ||  |  _  |  _  ||   _|   _|  _  |__ --|__ --|
|___._||__|_____|___._||____|__| |_____|_____|_____|

                     Unicode code point [A20] mapping to                      

 Font name                                                                   

 .LastResort                                                                 

 Arial Unicode MS                                                            

 Gurmukhi MN                                                                 

 Gurmukhi MT                                                                 

 Gurmukhi Sangam MN                                                          

 Mukta Mahee,MuktaMahee Bold                                                 

 Mukta Mahee,MuktaMahee ExtraBold                                            

 Mukta Mahee,MuktaMahee ExtraLight                                           

 Mukta Mahee,MuktaMahee Light                                                

 Mukta Mahee,MuktaMahee Medium                                               

 Mukta Mahee,MuktaMahee Regular                                              

 Mukta Mahee,MuktaMahee SemiBold

0 votes

Merci de votre attention ! (J'avais remarqué l'existence de albatross Je me souviens vaguement avoir posé cette question récemment et je voulais la retrouver et la mentionner, mais j'ai oublié Merci beaucoup d'avoir répondu, cela résout bien le problème. Il semble qu'il s'appuie sur fontconfig en interne).

0 votes

@ShreevatsaR De rien ! Oui, cela semble être similaire à votre réponse, juste un tout petit peu plus confortable à utiliser :)

LesApples.com

LesApples est une communauté de Apple où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres utilisateurs d'appareils Apple, poser vos propres questions ou résoudre celles des autres.

Powered by:

X