Connexion des polices sous Windows. Comment savoir quels caractères se trouvent dans une police

Nous continuons la série d'articles sur le développement de jeux mobiles. Dans cet article, je vais vous expliquer comment restituer du texte UTF-8 à l'aide de polices SDF Bitmap, comment créer ces polices et comment utiliser cette technique pour un rendu d'icônes de haute qualité.

FDS ( Champ de distance signé) est une image en niveaux de gris générée à partir d'une image en noir et blanc à contraste élevé dans laquelle le niveau de gris indique la distance jusqu'à la limite de contraste la plus proche. Cela semble déroutant, mais c'est en réalité très simple.


La police SDF elle-même ressemble à ceci :



Prenons cette image et modifions ses niveaux dans Photoshop ou tout autre éditeur graphique.



C'est déjà mieux ! Nous avons une police nette avec un anti-aliasing sur les bords.
Nous pouvons également obtenir un style audacieux ou fin. Mais malheureusement, vous ne pourrez pas obtenir l'italique.



Le principal avantage de SDF est la possibilité d'agrandir les polices sans artefacts visibles.



Comment créer une police SDF ?

Tout d’abord, vous devez créer une police bitmap noir et blanc très ordinaire. Vous pouvez le faire dans le bon vieux BMFont ou UBFG.


Pour de bons résultats, générez une taille de police de 400 pt, sans anti-aliasing, avec un remplissage de 45x45x45x45 et une taille d'image de 4096x4096. Pour de telles tailles, je vous conseille de désactiver la fusion car Très probablement, l'UBGF va geler.


Nous exportons l'image au format PNG sans transparence, et il est conseillé de sélectionner le format de description comme BMFont (pour une plus grande compatibilité).




convertir font.png -filter Jinc (+clone -negate -morphologie Distance euclidienne -niveau 50%,-50%) -morphologie Distance euclidienne -compose Plus -composite -niveau 43%,57% -redimensionner 12,5% ​​font.png

En sortie nous obtiendrons une image 512x512, ce qui nous donnera au final un très bon résultat.
A partir du fichier de description il faudra extraire les caractères en unicode et leur position/taille (n'oubliez pas de diviser les coordonnées par 8 puisque nous avons réduit l'image). Je vais vous dire exactement quels caractères doivent être exportés ci-dessous dans la section sur UTF-8.


Attendez une minute, UBFG a un champ de distance intégré !
Oui, je l'ai fait. Mais le résultat est nettement pire. Peut-être que les auteurs de l'UBFG corrigeront cela dans les mises à jour.

Shaders pour le rendu du texte

Shader de sommet pour imprimer chaque lettre, caractère par caractère :


#ifdef DEFPRECISION précision mediump float; #endif attribut mediump vec2 Sommet ; uniforme highp mat4 MVP ; cordons uniformes mediump vec2 ; moyenne variablep vec2 outTexCord ; void main())( outTexCord=Vertex*cords+cords; gl_Position = MVP * vec4(Vertex*cords+cords, 0.0, 1.0); )

DÉFPRÉCISION nécessaire pour OpenGL ES.
DANS cordons Et cordons nous transmettons la position et l'échelle du symbole sur l'écran.
Et dans cordons Et cordons- les coordonnées du caractère sur la texture de la police.


Nuancier de fragments


#ifdef DEFPRECISION précision mediump float; #endif variable mediump vec2 outTexCord; échantillonneur lowp uniforme2D tex0 ; couleur moyenne uniforme vec4 ; paramètres uniformes mediump vec2 ; void main(void)( float tx=texture2D(tex0, outTexCord).r; float a=min((tx-params.x)*params.y, 1.0); gl_FragColor=vec4(color.rgb,a*color. un);

DANS couleur transmettre la couleur et la transparence de la lettre.
Et à travers paramètres ajustez l’épaisseur et le lissage des bords de la police.


Si vous pouvez ajuster l’épaisseur de la police, alors vous pouvez également afficher un cadre !
Fragmenter un shader de texte avec bordure:


#ifdef DEFPRECISION précision mediump float; #endif variable mediump vec2 outTexCord; échantillonneur lowp uniforme2D tex0 ; couleur moyenne uniforme vec4 ; paramètres uniformes mediump vec4 ; uniforme mediump vec3 borderColor; void main(void)( float tx=texture2D(tex0, outTexCord).r; float b=min((tx-params.z)*params.w, 1.0); float a=clamp((tx-params.x) *params.y, 0.0, 1.0); gl_FragColor=vec4(borderColor+(color.rgb-borderColor)*a, b*color.a);

De plus, nous transmettons l'épaisseur, en lissant à params.zw et la couleur du cadre dans BorderColor.
Le résultat devrait ressembler à ceci :



Pour obtenir de beaux bords pour les petites et grandes tailles de texte, vous devez sélectionner différents paramètres de contraste/lissage ( paramètres) pour les petites polices et pour les grandes polices. Interpolez-les ensuite à la taille actuelle.


À mon avis, pour petites tailles bon ajustement :

  • style plus audacieux
  • bords plus lisses
  • la bordure est minime et floue pour ne pas onduler

Pour grande taille:

  • style de police plus fin
  • les bords sont très coupants
  • la bordure est plus grande et plus nette

Icônes


Les icônes plates sont devenues très populaires dans le design moderne. Il existe de nombreuses icônes vectorielles gratuites. Tout ce que nous avons à faire est d'assembler un atlas de textures en noir et blanc à partir des icônes nécessaires et de l'exécuter via ImageMagick de la même manière !


En conséquence, nous pouvons stocker des icônes à une résolution assez basse, mais obtenir de bons résultats lors de la mise à l'échelle et de la rotation des icônes !


En bonus, vous pouvez facilement ajouter un dégradé aux icônes. Pour cela, il suffit d'accrocher les couleurs aux sommets, et on obtiendra le dégradé en interpolant entre les points. Le dégradé radial devra être fait pixel par pixel dans le fragment shader.

UTF-8

Dans les projets modernes, plus personne n'utilise d'encodages sur un seul octet. Tout le monde est passé à UTF-8, wchar, unicode. Par exemple, il est pratique pour moi de travailler avec des chaînes en caractères UTF-8*.
UTF-8 est facilement décodé en Unicode et s'adapte parfaitement à Java/String et NSString.


Fonction de conversion UTF-8 vers Unicode :


static inline unsigned int UTF2Unicode(const unsigned char *txt, unsigned int &i)( unsigned int a=txt; if((a&0x80)==0)return a; if((a&0xE0)==0xC0)( a=(a&0x1F)<<6; a|=txt&0x3F; }else if((a&0xF0)==0xE0){ a=(a&0xF)<<12; a|=(txt&0x3F)<<6; a|=txt&0x3F; }else if((a&0xF8)==0xF0){ a=(a&0x7)<<18; a|=(a&0x3F)<<12; a|=(txt&0x3F)<<6; a|=txt&0x3F; } return a; }

Prime! Modification du registre d'un caractère Unicode.

statique en ligne non signé int majuscule (unsigned int a)( if (a>=97 && a<=122)return a-32; if(a>=224 && un<=223)return a-32; if(a>=1072 && un<=1103)return a-32; if(a>=1104 && un<=1119)return a-80; if((a%2)!=0){ if(a>=256 && un<=424)return a-1; if(a>=433 && un<=445)return a-1; if(a>=452 && un<=476)return a-1; if(a>=478 && un<=495)return a-1; if(a>=504 && un<=569)return a-1; if(a>=1120 && un<=1279)return a-1; } return a; } static inline unsigned int lowercase(unsigned int a){ if(a>=65 && un<=90)return a+32; if(a>=192 && un<=223)return a+32; if(a>=1040 && un<=1071)return a+32; if(a>=1024 && un<=1039)return a+80; if((a%2)==0){ if(a>=256 && un<=424)return a+1; if(a>=433 && un<=445)return a+1; if(a>=452 && un<=476)return a+1; if(a>=478 && un<=495)return a+1; if(a>=504 && un<=569)return a+1; if(a>=1120 && un<=1279)return a+1; } return a; }

Blocs UTF-8

La plupart des polices, en particulier les plus créatives, n'ont que des caractères ascii et latin. Et si nous avons besoin, par exemple, de symboles monétaires ? Cela est particulièrement vrai pour les paiements via l’application, pour lesquels toutes sortes de devises ne sont pas disponibles. Je propose le schéma suivant, qui a très bien fait ses preuves :



Comment savoir quels caractères contiennent une police ?


Ici, une chose étrange d'Adobe vient à notre aide - tada ! - police vide !
Il peut être utilisé en CSS : famille de polices : Roboto, Adobe Blank ;
C'est ainsi que les plaques de la photo ci-dessus ont été obtenues. Il ne reste plus qu'à copier les symboles nécessaires et à les coller dans UBFG. En conséquence, nous obtiendrons plusieurs images 512x512, chacune contenant autant de caractères qu'elle peut contenir.


Quelle est cette police universelle ?



Supposons que vous ayez ajouté des bitmaps pour l'arabe, le japonais et le chinois. Il y aura pas mal de photos. Ne vous précipitez pas pour tous les télécharger ! Attendez de tomber sur un symbole de ce bloc et chargez la texture souhaitée.


Il existe également un problème dans la mesure où toutes les polices sont de tailles différentes et ont des lignes de base différentes. Lorsque vous passez d'une police à l'autre, le texte sautera. Par conséquent, pour chaque police, sélectionnez les paramètres de son échelle relative et de son décalage Y. Tenez compte de ces paramètres lors du rendu de chaque caractère.


J'ai promis des petits pains !
Procurez-vous la police SDF Quivira prête à l'emploi, déjà découpée en blocs !

Dans cette leçon, nous verrons comment utiliser les polices Type1 ou TrueType afin que vous puissiez utiliser non seulement les polices standard. Une autre fonctionnalité est que vous pouvez choisir une police et un encodage qui vous permettront d'utiliser non seulement des langues occidentales mais également d'autres langues (les polices standard ont trop peu de caractères disponibles).

Il existe deux manières d'utiliser la nouvelle police : les polices intégrées au PDF ou les polices plug-in. Si la police que vous spécifiez n'est pas intégrée, elle sera recherchée dans le système. L'avantage des polices plug-in est que le fichier PDF est beaucoup plus léger et, d'autre part, s'il n'est pas disponible, une police standard est utilisée. Il est donc conseillé d'installer la police sur les systèmes clients. Si le fichier ne sera pas visualisé uniquement sur votre ordinateur local, vous devez alors l'insérer dans le PDF.

Pour ajouter de nouvelles polices TrueTypes, vous devez suivre trois étapes :

  • Générer un fichier de métriques (.afm)
  • Générer un fichier de définition de police (.php)
  • Déclarer une police dans un script

Pour Type1, la génération théorique d'un fichier AFM n'est pas nécessaire, puisque le fichier est généralement fourni avec la police. Si vous disposez uniquement d'un fichier de métrique au format PFM, vous pouvez utiliser le convertisseur fourni sur le site FPDF - http://www.fpdf.org/fr/dl.php?id=34.

Générer un fichier de métrique

La première étape pour TrueType consiste à créer un fichier AFM. Pour ce faire, vous devez utiliser l'utilitaire. Le binaire Windows est disponible à l'adresse suivante - http://www.fpdf.org/fr/dl.php?id=22.
Pour utiliser l'utilitaire ttf2pt1, saisissez ce qui suit sur la ligne de commande :
ttf2pt1 -une police font.ttf

Prenons par exemple la police Comic Sans MS Regular :
ttf2pt1 -a c:\windows\fonts\comic.ttf bande dessinée

À l'aide de cet utilitaire, deux fichiers sont créés, dont l'un est un fichier avec l'extension .afm, ce dont nous avons réellement besoin.

Générer un fichier pour définir une police

La deuxième étape consiste à créer un fichier PHP contenant toutes les informations nécessaires pour FPDF. Pour ce faire, dans le répertoire police/makefont Vous pouvez trouver un script supplémentaire dans le fichier makefont.php, qui contient les fonctions suivantes :
MakeFont (string fontfile, string afmfile [, string enc [, array patch [, string type]]])

Les valeurs que la méthode prend en paramètres :

  • fichier de police— Chemin d'accès au fichier avec l'extension .ttf ou .pfb.
  • fichier afm— Chemin d'accès au fichier avec l'extension .afm.
  • fr— Le nom de l'encodage utilisé. La valeur par défaut est cp1252.
  • correctif— Modifications supplémentaires concernant le codage. La valeur par défaut est vide.
  • taper— Type de police (TrueType ou Type1). La valeur par défaut est TrueType.

Le premier paramètre doit être le nom et le chemin d'accès à la police. L'extension doit être .ttf ou .pfb. Si vous disposez d'une police Type1 au format ASCII avec une extension .pfa, vous pouvez la convertir au format binaire à l'aide de l'utilitaire t1utils.

Fichier AFM généré précédemment

L'encodage définit la relation entre le code (0 à 255) et le caractère. Les 128 premiers sont fixes et correspondent à l'ASCII, et les suivants sont variables. Les encodages sont stockés dans des fichiers .map. Les codages sont les suivants :

  • cp1250 (Europe centrale)
  • cp1251 (cyrillique)
  • cp1252 (Europe occidentale)
  • cp1253 (grec)
  • cp1254 (turc)
  • cp1255 (hébreu)
  • cp1257 (Baltique)
  • cp1258 (vietnamien)
  • cp874 (thaïlandais)
  • ISO-8859-1 (Europe occidentale)
  • ISO-8859-2 (Europe centrale)
  • ISO-8859-4 (Baltique)
  • ISO-8859-5 (cyrillique)
  • ISO-8859-7 (grec)
  • ISO-8859-9 (turc)
  • ISO-8859-11 (thaïlandais)
  • ISO-8859-15 (Europe occidentale)
  • ISO-8859-16 (Europe centrale)
  • KOI8-R (russe)
  • KOI8-U (ukrainien)

La police que vous choisissez doit contenir des caractères correspondant à l'encodage sélectionné.
Dans les cas particuliers où les caractères de police ne contiennent pas de lettres, comme Symbol ou ZapfDingbats, vous devez transmettre une chaîne vide.
Les codages commençant par CP sont utilisés sous Windows. Les systèmes Linux utilisent généralement l'ISO.
Note: les polices standards utilisent l'encodage cp1252.

Le quatrième paramètre permet de modifier l'encodage. Parfois, vous pouvez ajouter plusieurs caractères. Par exemple, l'ISO-8859-1 ne contient pas le symbole de l'euro. Pour l'ajouter à la position 164, vous devez passer - tableau(164=>’Euro’).

Le dernier paramètre est utilisé pour transmettre le type de police au cas où il ne serait pas intégré (c'est-à-dire si le premier paramètre est vide).

Après avoir renseigné tous les paramètres de la fonction, vous pouvez créer un nouveau fichier en incluant makefont.php, ou simplement ajouter un appel de fonction directement dans le fichier principal. Après avoir exécuté la fonction, plusieurs fichiers seront créés : .php et .afm. Si vous le souhaitez, vous pouvez renommer le fichier. De plus, le script crée un fichier avec une extension .z, qui est compressé (sauf si la fonction de compression n'est pas disponible, elle nécessite Zlib). Vous pouvez aussi le renommer, mais dans ce cas vous devez changer la variable $fichier dans un fichier .php avec le nom approprié.

FaireFont( "c:\\windows\\fonts\\comic.ttf", "comic.afm" , "cp1252" ) ;

MakeFont("c:\\windows\\fonts\\comic.ttf","comic.afm","cp1252");

L'exemple ci-dessus créera deux fichiers : bande dessinée.php Et bande dessinée.z.

Lorsque vous recevez ces fichiers, vous devez les copier dans le répertoire des polices. Si le fichier de police n'est pas compressé, copiez les fichiers avec l'extension .ttf ou .pfb, au lieu de .z.

Note: pour les polices TTF, vous ne pouvez pas le faire manuellement mais téléchargez ces fichiers à l'aide de l'utilitaire à cette adresse : http://fpdf.fruit-lab.de/. Je pense que l'utilisation de ce script ne vous posera pas beaucoup de difficultés, mais quand même : vous devez sélectionner un fichier TTF sur votre ordinateur, puis en cliquant sur un seul bouton, vous obtiendrez les fichiers nécessaires pour FPDF.

Déclarer une police dans un script

La dernière étape est la plus simple. Il vous suffit d'appeler la méthode AddFont(). Par exemple:

$pdf->AddFont("Bande dessinée");

La police est maintenant prête à être utilisée. Si vous avez choisi une police différente, par exemple Comic Sans MS Bold (comicbd.ttf), alors vous devez la déclarer comme ceci :

$pdf -> AddFont ("Comic" , "B" , "comicbd.php" ) ;

$pdf->AddFont("Comic","B","comicbd.php");

Exemple

Voyons un petit exemple entièrement fonctionnel. La police Calligrapher sera utilisée, que vous pouvez télécharger sur le site - http://www.abstractfonts.com/ (un site qui propose un grand nombre de polices TrueType gratuites). Le lien de téléchargement de la police est http://www.abstractfonts.com/download/52. La première étape consiste à générer un fichier AFM :
ttf2pt1 -a calligra.ttf calligra

ce qui donne calligra.afm (et calligra.t1a, qui peut être supprimé). Ensuite, nous créons un fichier de définition :

require ("font/makefont/makefont.php" ) ;

MakeFont("calligra.ttf" , "calligra.afm" ) ;

require("font/makefont/makefont.php"); MakeFont("calligra.ttf","calligra.afm");
L'appel de la fonction produira les messages suivants :
Attention : le caractère Euro est manquant
Attention : le caractère eth est manquant
Fichier de police compressé (calligra.z)

Fichier de définition de police généré (calligra.php)
Le symbole de l'euro manque car il est trop ancien. D'autres symboles manquent également, mais nous n'en aurons pas besoin.

Vous pouvez maintenant copier les deux fichiers dans le répertoire et écrire le script :

exiger ("fpdf.php" ) ;

$pdf = nouveau FPDF() ;

$pdf -> AddFont ("Calligraphe" , "" , "calligra.php" ) ;

Dans différents encodages, le symbole de l'euro est situé à différentes positions, et en général il n'apparaît pas dans tous les encodages :

Codage

Position
128
136
128
128
128
128
128
128
128
absent
absent
absent
absent
absent
absent
Au lieu d'ISO-8859-2, vous pouvez utiliser ISO-8859-16, mais cet encodage contient de nombreuses différences. Il est donc plus simple d’ajouter ce caractère au codage, comme décrit ci-dessus. Il en va de même pour les autres codages.

Connexion des polices sous Windows

Si la police que vous choisissez n'est pas disponible dans un style particulier, Windows peut la combiner à partir de la version standard. Par exemple, il n'existe pas de Comic Sans MS Italic, mais il peut être construit à partir de Comic Sans MS Regular. Cette fonction peut être utilisée dans un fichier PDF, mais nécessite malheureusement que la police normale soit présente sur le système. Voici comment procéder :

  • Créez un fichier pour définir une police normale sans pièce jointe (vous souhaiterez peut-être le renommer pour refléter le style souhaité)
  • Ouvrez-le et ajoutez le style souhaité à la variable $name après la virgule (Italic, Bold ou BoldItalic)

Par exemple, pour le fichier comici.php cela ressemblerait à ceci :

$pdf->AddFont("Comic","I","comici.php");

Réduire la taille des polices TrueType

Les fichiers de polices sont souvent de très grande taille (plus de 100, voire 200 Ko), cela est dû au fait qu'ils contiennent des caractères qui correspondent à de nombreux encodages. La compression Zlib les réduit, mais ils restent assez importants. MAIS il existe encore une technique qui permettra de la réduire davantage. La technique est que lors de la conversion d'une police Type1 à l'aide de ttf2pt1, vous devez spécifier l'encodage dont vous avez besoin et tous les caractères correspondant à d'autres encodages seront ignorés.
Par exemple, la police arial.ttf fournie avec Windows 98 pèse 267 Ko (elle contient 1 296 caractères). Après compression, ce sera 147. Convertissons-le en Type1, en gardant uniquement les caractères nécessaires à l'encodage cp1250 :

Bonne chance dans votre utilisation !

) du Dr Markus Kuhn de Cambridge. Essentiellement, il s'agit simplement de texte codé en UTF-8, mais le problème est qu'il contient diverses fonctionnalités de codage, telles que la combinaison de caractères. Comme vous le verrez, les navigateurs affichent même le « texte simple » différemment à certains endroits et pas du tout à certains endroits. Tableau récapitulatif des réussites aux tests pour quelques grands noms (sous Windows 7 64 bits, polices par défaut) :

Il convient de noter que dans Chrome, Firefox, IE monospace La police par défaut est Courier New, dans Opera c'est Consolas.

Commentaires

Mathématiques et sciences
Chrome n'a pas pu trouver certains caractères et les a remplacés par des carrés. IE a tout trouvé, mais a abandonné

Firefox et Opera ont également tout trouvé, mais ont rendu la situation encore pire. Amaya n'a pratiquement rien trouvé.

Linguistique et dictionnaires

Aucune plainte à tous les participants.

Typographie plus agréable dans les fichiers texte brut

Seul Opera était capable d'afficher correctement les apostrophes frisées. Les autres ne pouvaient pas le supporter. Cependant, tout le monde a eu des problèmes près du coin inférieur droit du cadre.

Combinaison de personnages

L'idée est que les personnages soient regroupés au lieu d'être dessinés un par un. En général, ils ne dessinent pas encore. Il convient de noter qu'Opera a presque réussi - seul le signe vectoriel a échoué.

Grec (en polytonique), géorgien, russe

Les navigateurs acceptent les langues grecque, géorgienne et russe.

Thaï (UCS niveau 2)

Les symboles eux-mêmes ont été trouvés par tous les navigateurs. Cependant, en bas, il est indiqué que si le rendu est correct, il devrait y avoir deux colonnes paires. Cela n'arrive pas.

éthiopien

IE et Amaya n'ont pas trouvé la langue éthiopienne.

De vraies runes anciennes ! C'est dommage que Chrome et Amaya n'aient pas trouvé la police appropriée.

Braille

Police braille. Similaire au test précédent.

Exemple de texte de sélection de police compacte

IE et Amaya n'ont pas trouvé certains caractères et les ont remplacés par des carrés. Firefox a étrangement mis en retrait l'avant-dernière ligne.

Salutations en différentes langues

Tous les navigateurs ont réussi ce test.
Alignement du dessin de la boîte
Chrome

Internet Explorer

Firefox

Opéra

Amaya

CV

J'ai inclus Amaya 11 dans les tests parce que je pensais que puisqu'il s'agit du navigateur officiel du W3C, il devrait être plus pleinement conforme aux spécifications. Cependant, il a montré le résultat le plus faible. Opera prend à juste titre la tête des tests, mais même lui n'a obtenu que les deux tiers des points. Bien que les navigateurs modernes prennent en charge Unicode et la plupart des langages, le respect des normes est clairement médiocre. Bien sûr, personne dans la vie réelle ne tapera des cadres ou des guillemets arrondis en UTF-8, et ce n'est pas critique. Cependant, à la recherche de nouvelles balises HTML5 et de performances Javascript, les développeurs pourraient accorder davantage d'attention au rendu du texte UTF-8.

Des questions ?

Signaler une faute de frappe

Texte qui sera envoyé à nos rédacteurs :