Je laisse (temporairement ?) de côté la suite de mes rants contre le principe de précaution, parce que ça va sans doute me prendre encore beaucoup trop de temps d'écrire les numéros (2) et (3).
Mes déboires avec OpenOffice.org ont commencé lorsque mon poussinet, au cours d'une discussion sur des romans d'un auteur de heroic fantasy que nous apprécions tous deux (Raymond Feist), a appris que j'avais moi-même écrit un roman quand j'étais petit (roman qui est plus cher à mon cœur qu'il n'est littérairement potable), et il [le poussinet] a exprimé le désir[#] de le lire. Seulement, pour ça, il en fallait une version imprimée, la version HTML étant trop peu commode à lire (version HTML qui actuellement est là mais je compte la remplacer par mieux, justement, cf. ci-dessous). D'où l'idée, née de mon enthousiasme naïf et de la supposition candide que la technique marche parfois, d'en générer une version PDF par conversion d'une version OpenDocument via OpenOffice.org. [Ajout : voir cette entrée ultérieure au sujet de ce roman,]
Quelques explications sur les formats s'imposent peut-être.
Le format PDF est un format de description de document déjà mis en page mais vectoriel (vectoriel signifiant qu'il ne suppose pas une résolution particulière mais se décrit en termes de primitives graphiques générales comme des courbes de Bézier, ce qui permet de zoomer autant qu'on veut sans effet désagréable de pixelisation) : on peut s'imaginer qu'il contient des descriptions de texte dans différentes polices (les polices en question, a priori vectorielles, pouvant être embarquées dans le document ou supposées connues du lecteur) ou des commandes de dessin vectoriel. Un format de document mis en page suppose un format de papier bien défini (A4, B5, US legal, que sais-je encore), et a priori on ne peut pas en changer (sauf à appliquer un zoom ou à recentrer le texte dans la page), en tout cas on ne peut pas repaginer le document.
À l'opposé de tels formats mis en page
, on a des
formats sémantiques, dont un exemple serait
le DocBook, et qui
consistent à décrire le texte d'un document non par sa position dans
la page mais par sa fonction sémantique (telle que : titre de
chapitre, note en bas de page, citation en exergue, etc.). Pour
passer d'un format sémantique à un format mis en page (et bon à
imprimer), on va créer une feuille de style qui va indiquer
la façon dont on veut mettre en page les différentes fonctions
sémantiques reconnues dans le document (i.e., la police à utiliser
pour le titre, la taille des notes en bas de page, les marges des
citations en exergue) ; le contenu sémantique et la feuille de style
sont normalement gardés bien séparés (principe de séparation du fond
et de la forme), et un programme de mise en page va prendre les deux,
les passer à la moulinette et produire un PDF (ou tout
autre format mis en page).
Enfin, ça c'est la théorie. La pratique, c'est que rien n'est
parfait. Le PDF est un format qui a parfois des
problèmes incompréhensible (voir plus loin), et les formats
sémantiques on ne sait pas très bien où les trouver ; la séparation
fond/forme est un truc complètement théorique et qui marche très mal
sur des documents réels, notamment parce qu'un livre réel (sauf
peut-être s'il s'agit d'une documentation technique) va contenir
beaucoup de choses qui se placent dans une région bien floue entre le
fond et la forme (du genre : tel paragraphe est centré parce que
l'auteur a décidé de le centrer — on ne sait pas bien quelle est
la sémantique profonde derrière, etc.), du coup, on multiplie
les classes
ou les styles
de texte, et on finit par leur
donner des noms comme centré
ou aligné à droite
, et à ce
stade la distinction fond/forme part aux chiottes.
Quelque part entre les formats mis en page et les formats
sémantiques, on a le format OpenDocument, qu'on pourrait décrire comme
le format natif de OpenOffice.org (depuis la version 2) mais qui est
surtout l'alternative ouverte au format de Microsoft Word. Un fichier
au format OpenDocument est une archive
(zip)
contenant un certain nombre de fichiers,
principalement XML,
dont l'un (content.xml
) contient censément le fond et un
autre (style.xml
) est la feuille de style qui contrôle la
forme (les autres fichiers de l'archive contenant, par exemple, les
méta-données du document, les images, les macros, etc.).
L'idée que j'avais, et qui était parfaite en théorie, était la suivante : retravailler un peu le source du livre pour en avoir une version XML propre selon un schéma personnel[#2] à la sémantique aussi claire que possible, puis avoir des scripts qui pourraient convertir ce XML source soit en un format (X)HTML pour l'affichage comme page Web soit en un format OpenDocument qu'OpenOffice.org pourrait ensuite paginer et transformer en PDF. Ainsi, il me serait possible d'avoir simultanément une version HTML et une version PDF, les deux découlant d'un même source (donc si je corrige une faute d'orthographe dans le source, il n'est pas trop pénible de régénérer les deux versions publiées), et les deux étant de bien meilleure qualité que si je produisais le PDF directement à partir du HTML (ce qui est systématiquement épouvantable et ce qui interdit quelque chose comme une belle table des matières). Voilà, ça c'était la théorie. Comme d'habitude, il n'y a pas de différence entre la théorie et la pratique — en théorie.
Le roman était à l'origine écrit sur le traitement de texte Sprint de Borland (sous MS-DOS). Différentes manipulations de format l'avaient transformé en TeX, puis en HTML. Je n'ai pas eu beaucoup de mal, à l'aide de recherches-remplacements dans un quelconque éditeur, à sortir un fichier XML que je pouvais considérer comme un source primaire à utiliser désormais.
Première difficulté : comment écrire les scripts de
transformation ? S'agissant de transformer un
fichier XML (source) en un autre fichier XML
(le content.xml
du fichier OpenDocument), il y a un
langage a priori fait pour
ça : XSLT ;
mais XSLT est un langage de programmation très
particulier, qui n'a pas vraiment de variables ni de boucles au sens
où on l'entend habituellement, et qui, s'il facilite certaines
opérations, en rend d'autres absolument atroces, et notamment pour ce
qu'on appelle la fabrication des styles automatiques
OpenDocument, j'ai vite compris qu'utiliser XSLT
tournerait à la séance de SM cuir et chaînes. Donc je me
suis rabattu sur le langage général Perl et sa
bibliothèque XML::LibXML
pour manipuler du XML ; c'est certainement plus puissant
que XSLT, mais c'est aussi souvent inutilement verbeux,
par exemple quand je vois la quantité d'incantations propitiatoires
que je dois prononcer pour émettre trois malheureuses lignes
de XML définissant les polices du document :
$tgt_root->appendChild($tgt->createTextNode("\n")); $tgt_root->appendChild($tgt->createComment(" Font declarations ")); $tgt_root->appendChild($tgt->createTextNode("\n")); my $font_face_decls = $tgt->createElementNS($nspfx{"office"},"office:font-face-decls"); $tgt_root->appendChild($font_face_decls); $font_face_decls->appendChild($tgt->createTextNode("\n")); sub add_font_decl { my $font = $tgt->createElementNS($nspfx{"style"},"style:font-face"); $font_face_decls->appendChild($font); $font_face_decls->appendChild($tgt->createTextNode("\n")); $font->setAttributeNS($nspfx{"style"},"style:name",$_[0]); my $qname = $_[0]; $qname = "'" . $qname . "'" if $qname =~ / /; $font->setAttributeNS($nspfx{"svg"},"svg:font-family",$qname); $font->setAttributeNS($nspfx{"style"},"style:font-adornments",$_[1]); $font->setAttributeNS($nspfx{"style"},"style:font-family-generic",$_[2]); $font->setAttributeNS($nspfx{"style"},"style:font-pitch",$_[3]); } add_font_decl "DejaVu Serif", "Book", "roman", "variable"; add_font_decl "DejaVu Sans", "Book", "swiss", "variable"; add_font_decl "Linux Libertine", "Book", "roman", "variable"; $tgt_root->appendChild($tgt->createTextNode("\n"));
…beurk ! Comme d'habitude, le diable est dans les détails :
le principe général du code est facile à écrire (quand on lit
un <p>
dans le source, on émet
un <text:p>
à la sortie), mais plein de petits
problèmes viennent se greffer dessus et transformer le programme en
une tambouille illisible (pour générer le titre du livre tout entier,
que je veux centrer sur une page, il me faut émettre
un <text:p>
contenant
un <draw:frame>
contenant
un <draw:text-box>
contenant
un <text:p>
, et tout d'un coup je me rends compte
que certaines opérations appliquées dans mon programme à
un <text:p>
doivent ici s'appliquer
au <text:p>
intérieur et d'autres
au <text:p>
extérieur et que je dois tout d'un coup
les séparer — et hop, beaucoup de lignes de code en plus).
Autre aspect pénible : la feuille de style (le
fichier style.xml
du OpenDocument), que j'écris à la main
parce que c'est tout de même plus commode que de rajouter de la sauce
Perl autour, se met à contenir des choses que je voudrais bien générer
automatiquement (par exemple, le format OpenDocument ne permet pas de
contenir le plus simple calcul pour les marges : donc si je veux du
format papier B5 au lieu de A4 il faut que je recalcule plein de
choses).
Ensuite, on commence à tomber sur les bugs de OpenOffice (je ne
parle même pas des autres programmes censés pouvoir lire du
OpenDocument, tels que kword, abiword et okular : soit ils plantent
carrément en lisant mon fichier, soit ils en font de la bouillie pour
le formatage).
Il y
en a un qui m'a beaucoup énervé, qui concerne la table des
matières : normalement, le format OpenDocument prévoit que le document
peut contenir des balises <text:h>
pour délimiter
les divisions (chapitres, sous-chapitres, sections, sous-sections,
etc.) à faire figurer dans la table des matières, chacune étant
accompagnée d'un attribut numérique text:outline-level
qui indique le niveau d'imbrication (et typiquement, d'indentation
dans la table des matières) ; la balise peut aussi indiquer un style,
qui n'a a priori rien à voir avec le niveau d'imbrication (par
exemple, au même niveau d'imbrication, j'ai des titres de chapitre et
des balises de titres d'appendice) ; mais OpenOffice a un bug qui fait
qu'il traite ça n'importe comment : il prend le premier style
rencontré pour chaque niveau d'imbrication et décide que ce style (et
aucun autre) « est » ce niveau d'imbrication et ne fait figurer que
les paragraphes ayant ce style dans la table des matières. Pas de
moyen simple, donc, d'avoir une table des matières qui fera figurer à
même niveau d'imbrication les styles titre de chapitre
et titre d'appendice
. Ah si, on peut créer la table des
matières à
partir de styles additionnels
, ce qui fait ce que je veux
(au prix de la clarté sémantique du document), mais alors on tombe sur
un
autre bug qui fait qu'on n'aura pas d'hyperliens dans la table des
matières ! Je me frappe la tête contre les murs : adieu l'idée
d'obtenir un OpenDocument propre et clair. Bon, j'ai fini par trouver
une façon de plus ou moins satisfaisante de contourner le problème,
mais que de temps perdu à comprendre ce qui ne va pas, à soumettre des
bug-reports[#3], à décider de la
moins mauvaise façon de contourner le problème et ainsi de suite !
Autre limitation horripilante de
OpenOffice : impossible
de trouver un format vectoriel dans lequel je puisse inclure les
cartes censées illustrer le roman. En effet, OOo ne comprend pas le
format vectoriel SVG (et une limitation fondamentale,
l'absence de clipping dans le format de dessin vectoriel natif
OpenDocument, fait qu'aucun convertisseur n'a de chance de pouvoir
marcher), et il ne sait pas non plus inclure
d'images PDF. Reste le format EPS, qu'il
arrive plus ou moins à inclure et auquel j'ai pu convertir mes
cartes[#4], mais d'une part il
prend un temps fou à les afficher (parce qu'il appelle un programme
externe qui, pour une raison qui m'échappe, est infiniment lent dans
ce cas), et d'autre part, si on demande d'exporter le fichier
en PDF, les images en
question sont
alors rastérisées (c'est-à-dire qu'elles cessent d'être
vectorielles pour devenir des tableaux de pixels à une résolution
donnée) ; en revanche, bizarrement, si on imprime vers une imprimante
PostScript, les images en question restent vectorielles, et on peut
convertir ce fichier PostScript en PDF… mais on
perd les liens de la table des matières ! D'où la seule solution que
j'ai trouvée : produire deux fichiers PDF, l'un
par exportation depuis OpenOffice, l'autre en imprimant en PostScript
et en convertissant ensuite en PDF, puis utiliser un
programme (pdftk
) pour mélanger les pages de l'un et
l'autre fichier PDF afin d'avoir, au final, à la fois les
cartes au format vectoriel et les liens qui marchent depuis
la table des matières. Quelle horreur !
Encore un souci que j'ai rencontré : comment faire générer la table
des matières dès l'ouverture du document ? En effet, le fichier
OpenDocument que je produis n'est pas paginé (et pour cause, je compte
justement sur OpenOffice pour faire la mise en page), c'est-à-dire
qu'il ne contient ni sauts de ligne doux ni sauts de page doux (le mot
doux
— soft
— signifiant que
les sauts en question ont été calculés automatiquement et pas imposés
par la structure du document : la grande majorité des saux sont doux,
les sauts durs viennent avant un changement de chapitre pour ce qui
est des sauts de pages ou à la fin d'un vers pour les sauts de ligne,
bref, ce genre de choses). Du coup, la table des matières ne peut pas
contenir de numéros de pages, il faut la faire recalculer à OpenOffice
pour qu'elle en contienne. J'ai donc dû écrire une macro en basic
OOo, qui s'exécute à l'ouverture du document (en déclanchant toutes
sortes d'alarmes de sécurité, bien sûr, vu que le basic en question
n'est pas sécurisé), qui déclenche la réévaluation de la table des
matières. Il est vrai que, là, je m'attendais à avoir plus de mal que
ça, et que finalement ça a bien marché.
Mais ce n'est toujours pas la fin de mes ennuis : ensuite, il y a eu celui du choix de la police (il est vrai qu'OpenOffice n'a plus rien à voir là-dedans). J'aurais bien pris une des grandes polices traditionnelles (disons, [New] Century Schoolbook, qui me semble assez appropriée au caractère un peu enfantin du roman, mêlée à Univers ou Helvetica pour les titres et Optima pour la préface). Malheureusement, on connaît mon habitude de faire joujou avec Unicode : il a fallu que je misse des citations en grec et en russe dans le roman, et je n'ai pas de version grecque ou cyrillique des polices que je viens de citer (j'ignore même si quelqu'un en a fait une). Autre possibilité : Gentium, une police libre moderne dont j'apprécie l'élégance sobre et reserrée, et qui contient le grec polytonique et à peu près le cyrillique. Malheureusement, ce n'est qu'à peu près, puisque j'ai fini par me rendre compte qu'il me manquait encore quelques caractères (le cyrillique est très incomplet dans la version italique de la police). Finalement, je me suis rabattu sur Linux Libertine, une police libre très complète (et qui malgré son nom n'a absolument aucun rapport avec Linux), assez proche des classiques Baskerville et Janson, et pour les titres et la préface j'ai pris Vera Sans et Vera Serif respectivement (dans leur version DejaVu pour recouvrir plus de caractères Unicode).
Bon, l'un dans l'autre, après ces durs labeurs, j'ai réussi à obtenir ce fichier OpenDocument et ce fichier PDF. Pour l'imprimer, je n'ai pas pensé à des sites spécialisés d'impression sur demande comme Lulu.com[#5] (je croyais que ça n'existait qu'à partir d'une centaine d'exemplaires : là j'en voulais seulement un ou deux), du coup je suis bêtement allé dans une boutique de reprographie et d'impression numérique. Et là, les imprimantes+photocopieuses Canon, auxquelles l'impression a été confiée, n'ont pas du tout apprécié mon PDF : elles ont mis quelque chose comme trente secondes par page (du coup je suis revenu chercher le résultat le lendemain), sans évidemment la moindre explication sur ce qui prenait tellement de temps à imprimer. Du coup, beaucoup du bien que je pensais du format PDF est parti (mais je ne sais pas si la faute doit être imputée aux drivers Canon, à OpenOffice, ou à la façon un peu compliquée dont j'étais obligé de produire le PDF comme je l'ai expliqué plus haut).
Bon, maintenant, il ne me reste qu'à refaire un fichier HTML à partir du nouveau XML source que j'ai.
[#] À moins que ce soit pour me faire plaisir ? Mais feignons d'ignorer cette éventualité.
[#2] Le XML est un format complètement général qui permet de représenter tout et n'importe quoi comme donnée structurée (disons que c'est juste une façon de sérialiser un arbre abstrait sous forme de données textuelles) : pour donner un sens à du XML il faut décider du sens qu'on va donner aux différentes balises et comment on va autoriser à les emboîter (le schéma).
[#3] Soumettre un bug-report à un programme est souvent très long car non seulement on doit chercher à produire un fichier simple et clair qui illustre le bug, mais en plus il faut s'inscrire dans l'outil de rapport de bug, ce qui demande d'attendre un mail de confirmation de mot de passe, etc.
[#4] Non sans mal ! Je ne sais pas pourquoi, pour partir du fichier PS que j'avais, j'ai dû convertir en PDF, reconvertir le PDF en PS, et convertir ce PS-là en EPS pour avoir quelque chose que OpenOffice accepte de digérer.
[#5] Une utilité que j'aurais pu y trouver aurait été d'imprimer en B5 (j'aime bien le format B5, pour les livres). Las ! ils ne le proposent pas.