Packages LaTeX externes | Aspose.TeX pour Java
Packages LaTeX externes
Il existe un certain nombre de packages LaTeX courants inclus dans la bibliothèque Aspose.TeX pour Java. Vous n’avez donc pas à vous soucier de la manière de fournir ces packages au moteur TeX de la bibliothèque. Mais parfois (peut-être souvent) votre fichier LaTeX peut nécessiter un package au-delà du « bundle » de packages pris en charge « nativement ». Dans ce cas, vous pouvez essayer de fournir l’entrée requise, c’est-à-dire les fichiers source du package requis, en utilisant la méthode setRequiredInputDirectory() de l’instance de classe TeXOptions. Nous verrons comment cela fonctionne avec deux exemples.
Définissez inputFile sur le chemin complet du document LaTeX correspondant et outputDirectory sur un dossier de sortie existant. Les deux exemples de conversion produisent un PNG à 150 DPI. Importez les classes Aspose.TeX utilisées dans l’exemple choisi, com.aspose.tex.rendering.ImageDevice, com.aspose.tex.rendering.PngSaveOptions et, pour l’entrée ZIP, java.io.InputStream et java.nio.file.Files. Gérez ou déclarez les exceptions dans la méthode appelante. Appliquez une licence conformément au
guide des licences.
Entrée requise décompressée (package fancybox)
Disons que nous avons le fichier LaTeX simple suivant, qui est required-input-fs.tex de notre
exemple de solution :
1\documentclass{article}
2\usepackage[a6paper,landscape]{geometry}
3\usepackage{fancybox}
4\begin{document}
5Test: \fbox{
6 \begin{Bitemize}[b]
7 \item First item
8 \item A second one\\ on two lines
9 \item(2pt) A third with extra space
10 \end{Bitemize}
11}
12\par\bigskip
13Test: \fbox{
14 \begin{Beqnarray}
15 y & = & x^2 \\
16 a^2 + 2ab + b^2 & = & (a + b)^2 \\
17 \int_0^\infty e^{-ax} dx & = & \frac{1}{a}
18 \end{Beqnarray}
19}
20\end{document}La troisième ligne nécessite le package externe fancybox. Définissez packagesDirectory sur un dossier local contenant fancybox.sty et ses dépendances. L’exemple complet ci-dessous affecte ce dossier à RequiredInputDirectory et produit une image PNG. Le périphérique et les répertoires de travail restent ouverts jusqu’à la fin du travail, puis sont libérés ou fermés.

Voici le code source complet de l’exemple :
1// Render the fancybox document using external package sources from a local folder.
2// inputFile is the full TeX input path; packagesDirectory contains fancybox.sty.
3// outputDirectory is an existing output folder.
4TeXOptions options = TeXOptions.consoleAppOptions(TeXConfig.objectLaTeX());
5OutputFileSystemDirectory output = new OutputFileSystemDirectory(outputDirectory);
6InputFileSystemDirectory packages = new InputFileSystemDirectory(packagesDirectory);
7options.setOutputWorkingDirectory(output);
8options.setRequiredInputDirectory(packages);
9PngSaveOptions saving = new PngSaveOptions();
10saving.setResolution(150);
11options.setSaveOptions(saving);
12options.setInteraction(Interaction.NonstopMode);
13options.setTerminalOut(new OutputMemoryTerminal());
14ImageDevice device = new ImageDevice();
15TeXJobResult result;
16int pages;
17try {
18 result = new TeXJob(inputFile, device, options).run();
19 pages = device.getPageCount();
20} finally {
21 device.dispose();
22 output.close();
23 packages.close();
24}Entrée requise archivée (package pgfplots)
Supposons maintenant que nous ayons le fichier LaTeX suivant, également assez simple, qui est « require-input-zip.tex » de notre exemple de solution :
1\documentclass{article}
2\usepackage[margin=0.25in]{geometry}
3\usepackage{pgfplots}
4\pgfplotsset{width=10cm,compat=1.18}
5\begin{document}
6
7First example is 2D and 3D math expressions plotted side-by-side.
8
9%Here begins the 2D plot
10\begin{tikzpicture}
11\begin{axis}
12\addplot[color=red]{exp(x)};
13\end{axis}
14\end{tikzpicture}
15%Here ends the 2D plot
16\hskip 5pt
17%Here begins the 3D plot
18\begin{tikzpicture}
19\begin{axis}
20\addplot3[
21 surf,
22]
23{exp(-x^2-y^2)*x};
24\end{axis}
25\end{tikzpicture}
26%Here ends the 3D plot
27
28\end{document}Sur la 3ème ligne, nous voyons que le fichier nécessite le package pgfplots, qui n’est pas non plus supporté “nativement”. Encore une fois, nous supposons que nous avons les fichiers sources du paquet pgfplots. Il s’agit d’un ensemble assez important de fichiers répartis entre deux emplacements si vous les trouvez dans le répertoire d’installation de n’importe quelle application de composition LaTeX. Vous pouvez trouver le dossier pgfplots dans les dossiers \tex\generic et \tex\latex. Et le contenu de ces deux dossiers doit être fourni comme entrée requise dans la bibliothèque Aspose.TeX. Nous souhaitons que ces fichiers sources soient regroupés dans une archive ZIP, voici donc la présentation de l’archive :

Définissez packagesZip sur un java.nio.file.Path vers l’archive contenant les sources génériques et LaTeX du package. L’exemple Java complet ci-dessous l’ouvre avec Files.newInputStream(...) et affecte un InputZipDirectory à RequiredInputDirectory. L’argument de chemin de base vide sélectionne toute l’archive. Gardez le flux ZIP et le répertoire ouverts jusqu’à la fin du travail TeX, puis fermez-les. Le résultat est une image PNG avec les deux graphiques.

Voici le code source complet de l’exemple :
1// Render the 2D/3D plots using pgfplots package sources from a ZIP archive.
2// inputFile is the full TeX input path; packagesZip is a java.nio.file.Path.
3// outputDirectory is an existing output folder; the ZIP includes generic and latex sources.
4TeXJobResult result;
5int pages;
6try (InputStream zipStream = Files.newInputStream(packagesZip)) {
7 TeXOptions options = TeXOptions.consoleAppOptions(TeXConfig.objectLaTeX());
8 OutputFileSystemDirectory output = new OutputFileSystemDirectory(outputDirectory);
9 InputZipDirectory packages = new InputZipDirectory(zipStream, "");
10 options.setOutputWorkingDirectory(output);
11 options.setRequiredInputDirectory(packages);
12 PngSaveOptions saving = new PngSaveOptions();
13 saving.setResolution(150);
14 options.setSaveOptions(saving);
15 options.setInteraction(Interaction.NonstopMode);
16 options.setTerminalOut(new OutputMemoryTerminal());
17 ImageDevice device = new ImageDevice();
18 try {
19 result = new TeXJob(inputFile, device, options).run();
20 pages = device.getPageCount();
21 } finally {
22 device.dispose();
23 output.close();
24 packages.close();
25 }
26}REMARQUE : Le résultat a été vérifié à l’aide du package
pgfplotsversion 1.18.1. La version du packagepfginclus dans la bibliothèque Aspose.TeX est la 3.1.9a.
Utilisation de packages de polices externes
En règle générale, les distributions LaTeX sont livrées avec une sélection de polices par défaut pouvant être utilisées pour la composition. En plus de ces polices, Aspose.TeX propose plusieurs packages de polices non standard, tels que amsfonts, eurosym et wasysym. Comme mentionné précédemment, Aspose.TeX prend également en charge l’utilisation de packages externes, même si nous nous sommes principalement concentrés sur les packages qui n’incluent pas de polices.
L’extension du moteur Object TeX dans Aspose.TeX nécessite des cartes de polices, qui sont des fichiers texte avec l’extension .map qui spécifient les polices physiques correspondant au nom de police interne de chaque TeX. Ces cartes de polices doivent être chargées dans la mémoire de TeX pendant la phase d’initialisation et doivent être incluses dans les fichiers du package. Étant donné que le moteur ne connaît pas les noms de toutes les cartes de polices, il recherche tous les fichiers portant l’extension « .map ». Par conséquent, l’implémentation de l’interface
IInputWorkingDirectory utilisée comme valeur de l’option
RequiredInputDirectory doit fournir un moyen d’accéder à des collections de noms de fichiers en fonction de leur extension. Plus précisément, cette implémentation doit également implémenter l’interface
IFileCollector. Les implémentations standards,
InputFileSystemDirectory et
InputZipDirectory, remplissent déjà cette exigence.
Le RequiredInputDirectory personnalisé ci-dessous implémente les deux interfaces et lit les fichiers locaux explicitement enregistrés. Enregistrez-le sous RequiredInputDirectory.java avec ses imports inclus. Enregistrez chaque fichier avec storeFileName(...), affectez l’instance avec options.setRequiredInputDirectory(...) et fermez-la après le travail. Il s’agit d’un registre plat : les noms de fichier doivent être uniques lorsqu’ils sont demandés sans chemin complet. Les extensions sont comparées sans tenir compte de la casse ; le chemin de collecte facultatif sélectionne un répertoire du système de fichiers. Enregistrez tous les fichiers de package, de correspondance de polices, de métriques et de polices physiques nécessaires. La collecte rend les fichiers de correspondance détectables, mais ne fournit pas les données de polices manquantes.
1import com.aspose.tex.IInputWorkingDirectory;
2import com.aspose.tex.IFileCollector;
3import com.aspose.tex.TeXInputStream;
4import java.io.IOException;
5import java.io.UncheckedIOException;
6import java.nio.file.Files;
7import java.nio.file.Path;
8import java.nio.file.Paths;
9import java.util.ArrayList;
10import java.util.LinkedHashSet;
11import java.util.List;
12import java.util.Locale;
13import java.util.Set;
14
15// Register local package files explicitly, including font maps and their dependencies.
16// Save this class as RequiredInputDirectory.java and close it after the TeX job.
17public class RequiredInputDirectory implements IInputWorkingDirectory, IFileCollector {
18 private final Set<Path> files = new LinkedHashSet<Path>();
19 private final List<TeXInputStream> streams = new ArrayList<TeXInputStream>();
20
21 public void storeFileName(String fileName) {
22 Path file = Paths.get(fileName).toAbsolutePath().normalize();
23 if (!Files.isRegularFile(file)) {
24 throw new IllegalArgumentException("Package file does not exist: " + file);
25 }
26 files.add(file);
27 }
28
29 @Override
30 public TeXInputStream getFile(String fileName, boolean searchSubdirectories) {
31 // This registry is a flat virtual directory; only registered files are accessible.
32 for (Path file : files) {
33 if (file.toString().equals(fileName) || file.getFileName().toString().equals(fileName)) {
34 try {
35 TeXInputStream stream = new TeXInputStream(Files.newInputStream(file), file.toString());
36 streams.add(stream);
37 return stream;
38 } catch (IOException exception) {
39 throw new UncheckedIOException(exception);
40 }
41 }
42 }
43 return new TeXInputStream(null, fileName);
44 }
45
46 @Override
47 public String[] getFileNamesByExtension(String extension) {
48 return getFileNamesByExtension(extension, null);
49 }
50
51 @Override
52 public String[] getFileNamesByExtension(String extension, String path) {
53 String requested = extension.toLowerCase(Locale.ROOT);
54 if (!requested.isEmpty() && !requested.startsWith(".")) {
55 requested = "." + requested;
56 }
57 Path directory = path == null ? null : Paths.get(path).toAbsolutePath().normalize();
58 List<String> matches = new ArrayList<String>();
59 for (Path file : files) {
60 String name = file.getFileName().toString();
61 int dot = name.lastIndexOf('.');
62 String actual = dot < 0 ? "" : name.substring(dot).toLowerCase(Locale.ROOT);
63 if (actual.equals(requested) && (directory == null || file.getParent().equals(directory))) {
64 matches.add(file.toString());
65 }
66 }
67 return matches.toArray(new String[0]);
68 }
69
70 @Override
71 public void close() throws IOException {
72 IOException failure = null;
73 for (TeXInputStream stream : streams) {
74 try {
75 stream.close();
76 } catch (IOException exception) {
77 if (failure == null) { failure = exception; }
78 else { failure.addSuppressed(exception); }
79 }
80 }
81 streams.clear();
82 files.clear();
83 if (failure != null) { throw failure; }
84 }
85}Restrictions
Un package requis par votre fichier LaTeX peut être développé sous le noyau LaTeX3e. Un tel package ne fonctionnera probablement pas avec la bibliothèque Aspose.TeX puisque cette dernière est basée sur le noyau LaTeX2e.
De plus, un package requis par votre fichier LaTeX peut appeler directement des commandes primitives dépendantes du périphérique qui ne sont pas prises en charge par le moteur Object TeX de la bibliothèque Aspose.TeX. Malheureusement, un tel package ne fonctionnera pas à coup sûr.