\chapter{Générer des \og pdf\fg}
\label{chap-pdf}

\begin{introchap}{Cette annexe} présente un moyen de générer des
  documents au format Pdf (portable document format). Ce format créé
  par la société Adobe présente l'avantage d'être effectivement
  portable d'un ordinateur à un autre, et de manière plus générale,
  d'un système d'exploitation à un autre. Il est donc intéressant
  aujourd'hui de pouvoir générer de tels fichiers à partir d'un source
  \LaTeX{}.
\end{introchap}

\section{Principe général}

Il y a au moins trois façons de générer des fichiers au format Pdf à
partir d'un document \LaTeX{} :
\begin{enumerate}
\item à l'aide de \soft{pdflatex} qui s'utilise en lieu et place du
  programme \soft{latex} pour traduire le source \LaTeX{} en Pdf ;
\item à l'aide de \soft{dvipdf} permettant de traduire le fichier Dvi
  en Pdf ;
\item à l'aide de \soft{ps2pdf} pour traduire une sortie PostScript en
  Pdf.
\end{enumerate}

\begin{nota}
  Votre serviteur qui a une certaine expérience de la première
  solution s'attardera sur \soft{pdflatex}. Un des pré-requis pour une
  utilisation correcte de ce logiciel est 
  \begin{itemize}
  \item soit l'utilisation du package \ltxpack{lmodern} ;
  \item soit l'installation de l'extension « CM-Super font » de
    Vladimir {\rmfamily\textsc{Volovich}}. La distribution Etch de la
    Debian contient un paquet prêt à l'emploi. On peut également
    trouver des documentations sur le ouèbe permettant d'installer
    cette extension sur une distribution Debian Sarge avec te\TeX{}
    (\url{http://sravier.free.fr/linux/debian_latex_cm-super.html}).
  \end{itemize}
\end{nota}


\section{Ce qui change}

Pour compiler le fichier source \LaTeX{} et produire un fichier au
format Pdf, on utilisera le programme \soft{pdflatex} :
\begin{unixcom}
  pdflatex monfichier.tex
\end{unixcom}
commande qui, si le document source ne contient pas d'erreur, créera
le  fichier nommé \texttt{monfichier.pdf}. Voici ensuite quelques
remarques importantes :
\begin{description}
\item[Graphiques :] ils devront être inclus au format Png ou Jpeg pour
  les images et Pdf pour les dessins\footnote{Les fichiers du
    logiciel \soft{Xfig} peuvent être convertis en Pdf} ;
\item[Liens :] à condition d'inclure le package \ltxpack{hyperref}, le
  document Pdf contiendra automatiquement des liens à chaque
  occurrence de la commande \ltxcom{ref}, dans la
  table des matières, dans l'index, etc. De plus une table des
  matières déroulante sera générée pour le programme \soft{Acrobat
    Reader}.
\end{description}


\section{Trucs et astuces}

Puisqu'on génère souvent du Dvi ou du Pdf à partir du même source et
que l'on doit inclure des fichiers graphiques à des formats différents
selon la situation, on utilisera le package \ltxpack{ifpdf} et
l'astuce suivante :
\begin{verbatim}
\ifpdf
% un truc spécifique à la sortie en pdf
\else
% un machin spécifique à la sortie en dvi
\fi
\end{verbatim}


\subsection{Gestion des graphiques}

On pourra écrire ensuite quelque chose du genre :
\begin{verbatim}
\ifpdf
\graphicspath{{pngs/}{{pdfs/}}
\else
\graphicspath{{epss}}
\fi
\end{verbatim}
Si on a pris soin de ranger les fichiers graphiques dans les
répertoires \texttt{pngs}, \texttt{pdfs} et \texttt{epss}... Ce
nouveau « if » permet également des constructions du style :
\begin{verbatim}
\ifpdf
\includegraphics[pdftex]{graphicx}
\else
\includegraphics{graphicx}
\fi
\end{verbatim}
Ce qui ne doit pas être nécessaire avec les dernières moutures de
\LaTeX{}.


\subsection{Vignettes}

Les versions récentes de \soft{pdflatex} permettent de créer des
vignettes (\emph{thumbnail}) pour les visualiseurs \soft{evince} et
\soft{Acrobat Reader} pour ne citer qu'eux. Auparavant, il était
nécessaire d'utiliser le package \ltxpack{thumbpdf} :
\begin{ltxcode}
  \usepackage{thumbpdf}
\end{ltxcode}
puis exécuter :
\begin{unixcom}
  thumbpdf monfichier.pdf
\end{unixcom}
Cette commande crée un fichier nommé \texttt{monfichier.tpt} qui sera
inclus à la compilation suivante avec \soft{pdflatex}. 

\subsection{Pagination}

Pour faire apparaître les numéros de pages du document dans le
navigateur Acrobat Reader, il est nécessaire d'ajouter l'option
\texttt{pdfpagelabels} à l'inclusion du package \ltxpack{hyperref}
(cf. \S~suivant).

\subsection{Signets}

Les signets (\anglais{bookmarks} en anglais) des visualiseurs de
fichier~pdf sont des sortes d'« explorateurs de table des matières »
qui donnent accès directement à une section d'un niveau déterminé. Il
y a eu deux difficultés à contourner pour produire ce manuel :
\begin{enumerate}
\item faire en sorte que le contenu du « backmatter » (biblio,
  glossaire, index) soit au même niveau hiérarchique que les parties
  dans cet explorateur. Par défaut, ces informations se trouvent en
  effet « cachées » dans la partie des annexes, car à la même
  profondeur que les \ltxcom{chapter}s ;
\item faire en sorte que le lien vers l'index dans les signets pointe
  effectivement sur l'index...
\end{enumerate}
Pour régler le premier problème, il suffit de faire croire à \LaTeX{}
qu'à partir du « backmatter » les \emph{chapitres} sont d'un même
niveau de profondeur dans la table des matières, que les
\emph{parties}. L'incantation vaudou correspondante est :
\begin{ltxcode}
  \renewcommand{\toclevel@chapter}{-1}
\end{ltxcode}
à placer à un endroit judicieux dans un fichier de style. L'endroit où
l'on redéfinit le
\voir{sec-cosmetique-entete-pieddepage-backfrontmatter}{\ltxcom{backmatter}}
est sans nul doute un bon choix. 
\begin{notahack}
  Pour en finir avec les \anglais{bookmarks}, afin que celui de
  l'index pointe effectivement sur l'index (!), on devra cette fois
  avoir recours à une incantation chamanique :
  \begin{ltxcode}
    \let\printindexORIG\printindex
    \renewcommand{\printindex}{%
      \cleardoublepage
      \phantomsection% création d'une fausse section
      \addcontentsline{toc}{chapter}{Index}
      \printindexORIG}
  \end{ltxcode}
  \continuenota permettant de surcharger la commande
  \ltxcom{printindex} en y ajoutant une fausse section à l'aide de la
  commande \ltxcom{phantomsection} fournie avec le package
  \ltxpack{hyperref}. Ne m'en demandez pas plus~\jeblague{}
\end{notahack}

\section{Hyperliens}

Le package \ltxenv{hyperref} permet d'insérer dans les
fichiers~\texttt{.dvi} et~\texttt{.pdf} des commandes spéciales qui
pourront être exploitées par les navigateurs (\soft{xdvi} et
\soft{Acrobat Reader} entre autres). On pourra alors cliquer
sur le texte produit par les commandes telles que \ltxcom{ref} pour se
rendre automatiquement à la zone référencée. Dans le document que vous
avez sous les yeux, la version électronique possède des liens sur
lesquels on peut cliquer pour :
\begin{itemize}
\item toutes les références générées par \ltxcom{ref},
  \ltxcom{pageref} et \ltxcom{vref} ;
\item les notes de bas de page ;
\item les url produites par la commande \ltxcom{url} ;
\item les renvois bibliographiques ;
\item les pages pour chaque entrée d'index. 
\end{itemize}
Pour activer ce système d'hyperliens, on écrira :
\begin{ltxcode}
  \ifpdf
  \usepackage[pdftex=true,
              hyperindex=true,
              colorlinks=true]{hyperref}
  \else
  \usepackage[hypertex=true,
              hyperindex=true,
              colorlinks=false]{hyperref}
  \fi
\end{ltxcode}
Ce qui fera apparaître les liens en couleur uniquement dans la version
Pdf. Ceux de la version \postscript{} seront quant à eux produits en
noir ce qui assurera leur lisibilité si le document est imprimé en noir et
blanc.
\begin{notahack}
  L'ordre dans lequel on inclura les différents packages pour un
  document influera sur le bon fonctionnement de l'extension
  \ltxpack{hyperref}. Il arrive même que l'endroit choisi pour
  l'inclusion provoque une erreur de compilation. À vous de trouver la
  bonne séquence~\jeblague
\end{notahack}

\section{Interaction avec \soft{psfrag} et \soft{pstricks}}

\subsection{\soft{pstricks}}

\emph{To trick} en anglais, ou « tricher » en français... En gros en
écrivant ça :
\begin{ltxcode}[frame=single]
  Soit :
  \begin{pspicture}[](-1,-1)(1,1)
    \parametricplot[linewidth=.5pt,plotstyle=ccurve]%
    {0}{360}{4 t mul sin 3 t mul sin}
    \psgrid[gridlabels=0pt](-1,-1)(1,1)
  \end{pspicture}
  \quad le tracé de $x=\sin(4t), y=\sin(3t)$...
\end{ltxcode}
\includepstricksgraphics{pstricks-exemple}

Dingue, non ? Certes. Le principe de l'extension \ltxpack{pstricks}
est d'insérer du code \postscript{} dans le fichier \texttt{.dvi},
code qui pourra être également traité par le programme \soft{dvips}.
Là où ça se corse c'est lorsque l'on veut utiliser ces bestioles avec
\soft{pdflatex}. En effet ce dernier créant directement un fichier
\texttt{.pdf} à partir du \texttt{.tex}, insérer du \postscript{} dans
le fichier au format Pdf n'aura aucun effet... Il est malgré tout
possible de contourner le problème :
\begin{enumerate}
\item générer d'abord un document \LaTeX{} minimal contenant les
  commandes \ltxpack{pstricks} ;
\item compiler ce document avec \LaTeX{} pour générer un \texttt{.dvi}
  ;
\item demander à \soft{dvips} de créer un fichier au format
  \postscript{} encapsulé avec l'option \texttt{-E} ;
\item convertir ce fichier au format Pdf ;
\item inclure ce fichier au moment d'utiliser \soft{pdflatex}.
\end{enumerate}
Tout cela est évidemment un peu tordu mais peut être automatisé à
l'aide d'un Makefile, d'un petit script \unix{}, et d'une
commande... \framanouvellepage Tout d'abord :
\begin{ltxcode}
  \newcommand{\includepstricksgraphics}[1]{%
    \ifpdf\includegraphics{#1}\else\input{#1}\fi}
\end{ltxcode}
L'idée est donc d'extraire la portion de code contenant des commandes
\ltxpack{pstricks} pour les stocker dans un fichier
\texttt{bidule.tex}, puis lorsqu'on écrit :
\begin{ltxcode}
  \includepstricksgraphics{bidule}
\end{ltxcode}
on inclura \texttt{bidule.pdf} si on utilise \soft{pdflatex} et
\texttt{bidule.tex} si on utilise \LaTeX{}. Ensuite, le « petit »
script \unix{} qu'on peut adapter à ses besoins :
\begin{monverbatim}
  #!/bin/sh
  # on enlève l'extension du 1er argument
  FILE=${1%.*}
  # création d'un fichier temporaire psttemp.tex
  cat > psttemp.tex <<EOF
  \documentclass{manuel}¢ccomment«mettre la classe et les packages adéquats»
  \thispagestyle{empty}
  \begin{document}
  \input{$FILE}
  \end{document}
  EOF
  # Création du fichier dvi
  latex psttemp
  # Création du fichier eps
  dvips -E  $TMPFILE.dvi -o psttemp.eps
  # Création du fichier pdf
  epstopdf psttemp.eps --debug --outfile=$FILE.pdf
  # effacement des fichiers temporaires
  rm -f psttemp.* 
\end{monverbatim}
%$
Sauvé sous le nom \texttt{pstricks.sh}, ce script peut être invoqué
comme ceci :
\begin{unixcom}
  ./pstricks.sh bidule.tex
\end{unixcom}
et crée le fichier \texttt{bidule.pdf} que \soft{pdflatex}
aura la sagesse d'inclure grâce à la commande
\ltxcom{includepstricksgraphics} dont le code est donné plus
haut. Pour ce qui est du Makefile, il n'est pas très difficile à
partir du script précédent de définir une règle ayant pour but de
transformer un fichier \texttt{.tex} en un fichier \texttt{.pdf}. Avec
le version Gnu de \soft{make}, on aura quelque chose du genre :
\begin{monverbatim}
  %.pdf : %.tex
        ./pstricks.sh $<
\end{monverbatim}
\begin{notahack}
  Le programme \soft{dvips} n'est pas toujours en mesure de calculer
  correctement la boîte englobante pour le \postscript{} encapsulé. En
  particulier la section~41 de la documentation de
  \soft{pstricks}\footnote{\url{http://tug.org/PSTricks}} indique que
  \soft{dvips} n'est pas capable de tenir compte du code postscript
  généré pour estimer cette boîte englobante.  Dans ce cas, il est
  conseillé soit d'ajouter du texte autour du graphique et
  \soft{dvips} arrive à s'en sortir, soit d'utiliser l'environnement
  \ltxenv{TeXtoEPS}. Le document temporaire du script précédent
  devient alors :
\begin{monverbatim}
  cat > psttemp.tex <<EOF
  \documentclass{manuel}
  \usepackage{pst-eps}
  \thispagestyle{empty}
  \begin{document}
  \begin{TeXtoEPS} ¢ccomment«Pour aider PSTricks à calculer la boîte»
  \input{$FILE}
  \end{TeXtoEPS}
  \end{document}
  EOF
\end{monverbatim}
\end{notahack}

\subsection{\soft{psfrag}}

La limitation et le principe sont les mêmes que pour
\ltxpack{pstricks}. Pour utiliser \ltxpack{psfrag} avec
\soft{pdflatex}, il est nécessaire de procéder comme suit :
\begin{enumerate}
\item générer d'abord un document \LaTeX{} minimal contenant des
  commandes \ltxpack{psfrag} ;
\item compiler ce document avec \LaTeX{} pour générer un \texttt{.dvi}
  ;
\item demander à \soft{dvips} de créer un fichier au format
  \postscript{} encapsulé avec l'option \texttt{-E} ;
\item convertir ce fichier au format Pdf ;
\item inclure ce fichier au moment d'utiliser \soft{pdflatex}.
\end{enumerate}
Il y a cependant un petit « hic » car la figure dont on calcule la
boîte englobante avec \soft{dvips} contient du texte généré par
\soft{psfrag} indiquant les remplacements qui seront effectués. On
doit en tenir compte. Dans le script shell, on crée une fonction :
\begin{monverbatim}
  function genere_eps
  { 
    cat > $TMPFILE.tex <<EOF
  \documentclass{manuel}¢ccomment«mettre la classe et les packages qui vont bien»
  \thispagestyle{empty}
  \begin{document}
    \input{$1}
  \end{document}
  EOF
    echo "Création du fichier dvi"
    latex $TMPFILE > $LOGFILE
    echo "Création du fichier $TMPFILE.eps"
    dvips -E  $TMPFILE.dvi -o $TMPFILE.eps >> $LOGFILE 2>&1
  }
\end{monverbatim}
On utilise ensuite cette fonction par deux fois comme suit, dans le
script :
\begin{monverbatim}
  FILE=${1%.*}
  TMPFILE=truc
  LOGFILE=truc.log
  sanspsfrag=$TMPFILE-sanspsf.tex

  # on enlève les lignes contenant la commande \psfrag
  # et on récupère la boîte englobante du fichier eps 
  # sans les psfrag
  grep -v \\\\psfrag $FILE.tex > $sanspsfrag
  genere_eps $sanspsfrag
  bonnebb=$(grep "^%%BoundingBox" $TMPFILE.eps | head -1)

  # on récupère la boîte englobante du fichier eps
  # avec psfrag
  genere_eps $FILE
  mauvaisebb=$(grep "^%%BoundingBox" $TMPFILE.eps | head -1)

  # on remplace la boîte englobante par la bonne
  sed  -i "s/$mauvaisebb/$bonnebb/" $TMPFILE.eps 

  echo "Création du fichier pdf"
  epstopdf $TMPFILE.eps --debug \
  --outfile=pdfs/${FILE##*/}.pdf >>  $LOGFILE 2>&1

  # un petit coup de toilette
  rm -f $TMPFILE.* $LOGFILE $sanspsfrag
\end{monverbatim}
\begin{nota}
  Ce script a plusieurs limitations. Parmi elles : il échouera si une
  commande \verb+\psfrag+ s'étend sur plusieurs lignes. On demande en
  effet à \soft{grep} d'enlever les lignes contenant \verb+\psfrag+
  sans vérifier que la commande ne se termine pas une ou plusieurs
  lignes plus bas...
\end{nota}

%%% Local Variables: 
%%% mode: latex
%%% TeX-master: "../framabook"
%%% End: 
