Je vais dans ce document expliquer comment utiliser LaTeX pour taper des langues orientales (vous savez, celles avec tous les caractères bizarres), et en particulier comment utiliser pour ça des polices TrueType, tout en travaillant avec du PostScript.
Je suppose dans à peu près tout le texte que vous disposez d'un environnement de travail correct, avec un interpréteur de commandes de type Unix correct, et un interpréteur Perl. Ce n'est pas complètement indispensable, mais il faudra adapter les commandes à votre sauce si ce n'est pas votre cas.
Avant toutes choses, il vous faut des polices. Pour du chinois, vous pouvez utiliser les polices Arphic, qui sont libres, et jolies.
Pour du japonais, il est possible d'utiliser les
polices Wadalab. Il faudra
dans ce cas télécharger également tools/wftodm.c
.
Plus généralement, on pourra utiliser des polices internationales comme Arial Unicode (vendue avec je ne sais quel produit microsoft, franchement moche, mais extrêmement complète) ou Bitstream Cyberbit.
Sauf si vous comptez utiliser uniquement les polices Wadalab, qui sont déjà
en Type1, il vous faudra
Ttf2pt1. La version que j'ai
souffre d'une limitation pénible, à modifier d'urgence : dans
global.h
, remplacer la définition de ENCTABSZ
à
1024
par 65536
.
Il peut être également utile de disposer des
Type1 utilities, qui
permettent de manipuler des polices Type, en particulier de convertir des
.pfa
en .pfb
, ce qui a pour quasi-unique effet de
faire gagner de la place.
Il vous faut une version récente du package UCS, au moins novembre 2002.
Il vous faut égelement le package CJK.
Tous les deux devraient être inclus dans n'importe quelle bonne distribution, mais le package UCS sera peut-être un peu trop vieux.
TeX a son propre mécanisme de polices, et il va falloir y adapter les polices que vous avez trouvées. En particulier, TeX travaille surtout avec du PostScript, donc du Type1, alors que vous avez plus de chance de trouver du TrueType. Voici comment convertir.
Pour commencer, il faut apprendre à ttf2pt1
le nommage habituel
des caractères Unicode dans les polices Type1. Pour ça, il faut créer un
fichier unicode.map
, dont les lignes sont de la forme :
!X U+XXXX uniXXXX UNICODE CHARACTER
Avec x de 0 à 65535. Manque de chance, une exigence pénible de
afm2tfm
impose que les caractères ASCII (32 à 126) portent leur
nom officiel PostScript, qu'on peut obtenir de GhostScript avec la commande
StandardEncoding ==. Voici quelques lignes de Perl pour le
générer :
@e=qw{space exclam quotedbl numbersign dollar percent ampersand quoteright parenleft parenright asterisk plus comma hyphen period slash zero one two three four five six seven eight nine colon semicolon less equal greater question at A B C D E F G H I J K L M N O P Q R S T U V W X Y Z bracketleft backslash bracketright asciicircum underscore quoteleft a b c d e f g h i j k l m n o p q r s t u v w x y z braceleft bar braceright asciitilde}; for $i (0..65535) { $c = $i>31 && $i<127 ? $e[$i-32] : sprintf "uni%4.4X", $i; printf "!%X U+%4.4X %s UNICODE CHARACTER\n", $i, $i, $c; }
Quand on a ce fichier, il suffit d'appeler ttf2pt1
pour générer
les polices Type1 :
ttf2pt1 -O h -L unicode.map -b police.ttf
Ceci produit deux fichirs : police.pfb
, la police
proprement dite, qui risque d'être 60% plus grosse que le fichier TrueType
original, et police.afm
, le fichier de métrique, qui
va être nécessaire pour la suite. On met l'option -O h
qui
désactive les hints pour deux
raisons : d'une part ils peuvent faire déborder la capacité de
l'interpréteur PostScript (ça m'est précisément arrivé avec Bitstream), et
d'autre part dvips
ne sait pas les télécharger partiellement,
ce qui se traduit par un surcoût fixe de plusieurs méga-octets par police.
Note : la conversion va probablement produire beaucoup de warnings, ils ne sont a priori pas importants.
Les polices de TeX sont limitées à 256 caractères. Pour gérer les langues orientales, il faut en combiner plusieurs. Le package CJK définit un certain nombre d'encodages pour ça :
Un fichier d'encodage est de la forme /NomEncodage
[
, puis 256 noms de caractères PostScript, puis ] def
.
Nous allons générer des fichiers d'encodage pour C00, C10 et C40 à partir
des fichiers data/uni-*.def
présents dans le package UCS. Pour
ça, utilisons encore un script
Perl, un peu plus complexe cette fois. Il faut l'appeler avec en
argument tous les fichiers data/uni-*.def
.
Ce script reconnaît les lignes de la forme
\uc@dclc{u}{c}{v}
, où
u est le numéro Unicode d'un caractère (en décimal), c
l'encodage (cjkbg5
pour C00, cjkgb
pour GB et
cjkjis
pour C40 et C42), et v les macros TeX
nécessaires pour obtenir le caractère u dans une police
d'encodage c.
Pour C00, v est de la forme
\u@cjk@BgvXXYY
, ce qui veut dire le
caractère YY (en hexadécimal) de la police XX (en
décimal). Pour C10, v est de la forme
\u@cjk@GBXXYY
, avec le même codage. Pour
C40 et C42, v vaut
\jischarXXYY
, ce qui indique que le
caractère est à trouver à la position XX×0x5E+YY-0xB3F
(tout en hexadécimal) ; pour C40, le caractère n est simplement
le caractère x de la police y est celui de numéro
x+y×256, tout simplement.
Quand on a les encodages, on peut les utiliser pour générer les fichiers
.tfm
, qui permettent à TeX de savoir où placer les lettres,
ainsi que les fichiers .vf
dont je n'ai jamais compris
l'utilité.
On est maintenant confronté à un détail important : choisir un nom TeX pour
la police. La documentation du package CJK conseille d'avoir deux lettres
pour évoquer l'encodage (gs
pour du GB pour du
Chinois Simplifié, etc.), deux lettres pour nommer la
police, et deux lettres pour indiquer sa taille normale (dans le cas de
polices vectorielles, ce n'est pas très pertinent).
Ici, je fais avec Arphic PL Mingti2L en Big5 (soit avec C00), et je vais
l'appeler btmi10
.
Pour chacun des fichiers uniC00XX.enc
, il faut
exécuter la commande suivante :
afm2tfm police.afm -P uniC00XX.enc -v btmi10XX.vpl btmi10XX.tfm
Avec le shell Zsh, on peut faire ça avec une commande de la forme (il y aurait moyen de faire plus simple, mais ça produirait des fichiers vides pénibles pour les polices 3, 4 et 5 de C40) :
for i in uniC00*.enc; do j=$i[7,8] afm2tfm police.afm -P uniC00$j.enc -v btmi10$j.vpl btmi10$j.tfm done
Pour chaque police, afm2tfm
écrit une ligne de la forme :
btmi10XX ShanHeiSun-Light " LaTeXC00XXEncoding ReEncodeFont " <uniC00XX.enc
Ce sont les lignes nécessaires pour informer dvips
de comment
les trouver ; ShanHeiSun-Light
est le nom PostScript de la
police sur laquelle je fais cet exemple. Il faut les regrouper toutes dans
un fichier, disons btmi10.map
. Hélas, afm2tfm
oublie de préciser qu'il faut aussi télécharger la police dans l'imprimante.
Il faut donc ajouter à la fin de chaque ligne, avec un espace devant
<police.pfb
. Dans mon exemple, je me retrouve
avec un fichier de 54 lignes presque identiques, dont la première est :
btmi1001 ShanHeiSun-Light " LaTeXC0001Encoding ReEncodeFont " <uniC0001.enc <bsmi00lp.pfb
Pour en finir avec ces polices virtuelles, il faut encore faire deux
choses : d'abord compiler les fichier .vpl
, ce qui se fait par
exemple avec une commande comme celle-ci (toujours en Zsh) :
for i in *.vpl vptovf $i
On eut ensuite supprimer les .vpl
. Enfin, il faut informer
dvips
de l'existence de btmi10.map
, ce qui se fait
en ajoutant la ligne suivante dans ~/.dvipsrc
(ou dans les
config.*
de dvips
pour une installation
commune) :
p+ btmi10.map
Les polices japonaises Wadalab ont la particularité d'être déjà en
PostScript et déjà découpées en petits fichiers. Il y a dans ce cas
nettement moins de travail. La première chose à faire, après avoir
décomprimé l'archive, est de construire les polices Type1 en C42. Vous avez
besoin du programme wftodm.c
. Hélas, dvips
n'est
pas capable de télécharger partiellement les polices qu'il produit, à cause
d'un tout petit problème de forme. Un
patch trivial suffira : cherchez les
deux lignes suivantes (qui sont tout près l'une de l'autre, au voisinage de
la 215 dans la version que j'ai) :
fprintf(ofp,"/DmEncoding [\n"); fprintf(ofp,"/Encoding DmEncoding def\n");
Dans la première, supprimez le Dm
, et supprimez entièrement la
seconde. Compilez le programme, et appelez-le à peu près ainsi (je prends
l'exemple des polices Mincho) :
./wftodm -FontBase jmin min-*.ps
Vous vous retrouvez avec des .pfa
(polices Type1) et des
.afm
(métriques). Vous pouvez convertir les .pfa
en .pfb
pour économiser de la place si vous voulez.
Convertissez les .afm
en .tfm
(métriques pour TeX
avec :
for i in *.afm afm2tfm $i
Ceci vous affiche plein de lignes constituées essentiellement de deux fois
le nom de base des fichiers. Notez-les dans un fichier
jmin.map
, en ajoutant à la fin
<fichier.pfa
(ce qui fait donc trois fois le nom
répété chaque ligne).
LaTeX apporte une couche d'abstraction supplémentaires pour les polices :
le NFSS. Il faut prévenir ce mécanisme que nos polices existent. Pour ça, il
faut choisir un nom de famille pour notre police. Ici, disons
min
. Alors il faut créer un fichier c00min.fd
, qui
contient simplement :
\DeclareFontFamily{C00}{min}{} \DeclareFontShape{C00}{min}{m}{n} { <-> CJK * btmi10}{}
Écrire le document lui-même est très facile, c'est bien pour ça qu'on a fait tout ce boulot à l'avance. Il faut quelques packages et quelques options au début :
\usepackage[cjkbg5]{ucs} \usepackage[utf8]{inputenc} \usepackage[C00,T1]{fontenc} \DeclareFontSubstitution{C00}{min}{m}{n}
La première ligne charge le package UCS, et l'informe qu'on va travailler
principalement en chinois traditionel (Big5). Je rappelle que les autres
options sont cjkgb
pour le chinois simplifié,
cjkjis
pour le japonais, et d'autres que vous trouverez dans la
doc d'UCS. Le fait de dire à UCS quel langue on va faire lui permet de bien
choisir quand un même caractère est disponible à la fois en Big5 et en GB.
La deuxième ligne dit qu'on va taper en UTF-8, la troisième qu'on va
utiliser l'encodage C00 (et il faut aussi charger T1 pour ce qui n'est pas
dans C00). Enfin, la dernière indique qu'on veut utiliser min
comme famille par défaut en encodage C00.
Pour taper le texte lui-même, il suffit d'utiliser un éditeur en UTF-8. On peut par exemple utiliser mon programme termim, qui permet de taper diverses langues dans un terminal UTF-8 (mais pas (encore) le chinois traditionel).
Il restera peut-être à jouer avec babel
pour adapter la
typographie aux diverses langues, mais c'est un tout autre problème. Il ne
reste plus qu'à compiler. Attention, lancer xdvi
sur le
résultat peut être hasardeux pour la santé : quand j'ai essayé, il a bouffé
presque 1 Go de mémoire avant de se faire tuer par le noyau. On préférera
dvips
. Attention, certaines versions trop anciennes (mais pas
si anciennes que ça) ont de gros bugs qui empêcheront le téléchargement
partiel de la police ; ça ne marche pas avec une 5.86, mais ça marche avec
une 5.86e.
Pour donner une idée du coût de ces polices, chaque caractère différent utilisé va coûter environ entre 1,5 et 4,5 ko.
Il faut bien l'avouer, les histoires de noms des polices, c'est un fouillis assez immonde. Le pire est atteint pour les noms des polices au niveau de TeX, où l'ancienne limite des 8 caractères, encore vaguement respectée, moins les deux pour le numéro de police, conduit à des contorsions extrêmement pénibles. De plus, il existe différents schémas de nommage plus ou moins incompatibles. Je pense qu'il ne faut pas y prêter trop d'importance : choisissez un schéma, suivez-le vaguement, et ne vous posez pas de questions.
Quand tout marche bien sur deux ou trois exemple, il reste à mettre tout ça
en place. Les distributions récentes ont un schéma de répertoires standard
pour ça (en supposant que vous mettiez tout dans un répertoire
texmf/
) :
.afm
.tfm
.vf
.pfa
et
.pfb
.fd
.enc
et
.map
(sauf unicode.map
, qui n'est plus
nécessaire)
Si vous respectez cette structure, avec une installation moderne de TeX, il
suffit de positionner la variable d'environnement HOMETEXMF
(pour une installation personnelle) ou TEXMFLOCAL
à ce
répertoire pour que tout soit trouvé automatiquement. D'ailleurs, beaucoup
d'installations ont des valeurs par défaut de ~/texmf
et
/usr/local/share/texmf
(parfois lib
plutôt que
share
) respectivement.
Comme je suis bonne pâte, je vous mâche le travail : voici une
archive (592 ko) contenant les
fichiers d'encodage (unicode.map
et uniC*.enc
). Au
moins, si jamais il vous manque l'interpréteur Perl, vous pourrez continuer.
J'aurais pu donner cette archive dès le début, mais on aurait pu se demander d'où sortaient tous ces nombres magiques : je voulais montrer qu'on pouvait se débrouiller sans connaissance préalable autre que la bonne connaissance des formats et des mécanismes. D'ailleurs, les fichiers d'encodages du package UCS ne sortent pas non plus d'un chapeau : ils viennent des bases de données publiées par le Consortium Unicode.
De plus, comprendre la méthode dans ces cas permettra de l'adapter à des situations que je n'ai pas traitées, à commencer par le coréen (qui se traite exactement comme le chinois, à première vue).
Amusez-vous bien.