MDL-51784 general: Adding missing php4 style constructors
[moodle.git] / filter / tex / latex.php
blob685fca8b53a7655871d9e2441d3066d8ca365a4f
1 <?php
2 // latex.php
3 // render TeX stuff using latex - this will not work on all platforms
4 // or configurations. Only works on Linux and Mac with appropriate
5 // software installed.
6 // Much of this inspired/copied from Benjamin Zeiss' work
8 class latex {
10 var $temp_dir;
11 var $error;
13 /**
14 * Constructor - create temporary directories and build paths to
15 * external 'helper' binaries.
16 * Other platforms could/should be added
18 public function __construct() {
19 global $CFG;
21 // construct directory structure
22 $this->temp_dir = $CFG->tempdir . "/latex";
23 make_temp_directory('latex');
26 /**
27 * Old syntax of class constructor. Deprecated in PHP7.
29 public function latex() {
30 self::__construct();
33 /**
34 * Accessor function for support_platform field.
35 * @return boolean value of supported_platform
37 function supported() {
38 return $this->supported_platform;
41 /**
42 * Turn the bit of TeX into a valid latex document
43 * @param string $forumula the TeX formula
44 * @param int $fontsize the font size
45 * @return string the latex document
47 function construct_latex_document( $formula, $fontsize=12 ) {
48 global $CFG;
50 $formula = filter_tex_sanitize_formula($formula);
52 // $fontsize don't affects to formula's size. $density can change size
53 $doc = "\\documentclass[{$fontsize}pt]{article}\n";
54 $doc .= get_config('filter_tex', 'latexpreamble');
55 $doc .= "\\pagestyle{empty}\n";
56 $doc .= "\\begin{document}\n";
57 //dlnsk $doc .= "$ {$formula} $\n";
58 if (preg_match("/^[[:space:]]*\\\\begin\\{(gather|align|alignat|multline).?\\}/i",$formula)) {
59 $doc .= "$formula\n";
60 } else {
61 $doc .= "$ {$formula} $\n";
63 $doc .= "\\end{document}\n";
64 return $doc;
67 /**
68 * execute an external command, with optional logging
69 * @param string $command command to execute
70 * @param file $log valid open file handle - log info will be written to this file
71 * @return return code from execution of command
73 function execute( $command, $log=null ) {
74 $output = array();
75 exec( $command, $output, $return_code );
76 if ($log) {
77 fwrite( $log, "COMMAND: $command \n" );
78 $outputs = implode( "\n", $output );
79 fwrite( $log, "OUTPUT: $outputs \n" );
80 fwrite( $log, "RETURN_CODE: $return_code\n " );
82 return $return_code;
85 /**
86 * Render TeX string into gif/png
87 * @param string $formula TeX formula
88 * @param string $filename filename for output (including extension)
89 * @param int $fontsize font size
90 * @param int $density density value for .ps to .gif/.png conversion
91 * @param string $background background color (e.g, #FFFFFF).
92 * @param file $log valid open file handle for optional logging (debugging only)
93 * @return bool true if successful
95 function render( $formula, $filename, $fontsize=12, $density=240, $background='', $log=null ) {
97 global $CFG;
99 // quick check - will this work?
100 $pathlatex = get_config('filter_tex', 'pathlatex');
101 if (empty($pathlatex)) {
102 return false;
104 $pathlatex = escapeshellarg(trim($pathlatex, " '\""));
106 $doc = $this->construct_latex_document( $formula, $fontsize );
108 // construct some file paths
109 $convertformat = get_config('filter_tex', 'convertformat');
110 if (!strpos($filename, ".{$convertformat}")) {
111 $convertformat = 'png';
113 $filename = str_replace(".{$convertformat}", '', $filename);
114 $tex = "{$this->temp_dir}/$filename.tex";
115 $dvi = "{$this->temp_dir}/$filename.dvi";
116 $ps = "{$this->temp_dir}/$filename.ps";
117 $img = "{$this->temp_dir}/$filename.{$convertformat}";
119 // turn the latex doc into a .tex file in the temp area
120 $fh = fopen( $tex, 'w' );
121 fputs( $fh, $doc );
122 fclose( $fh );
124 // run latex on document
125 $command = "$pathlatex --interaction=nonstopmode --halt-on-error $tex";
126 chdir( $this->temp_dir );
127 if ($this->execute($command, $log)) { // It allways False on Windows
128 // return false;
131 // run dvips (.dvi to .ps)
132 $pathdvips = escapeshellarg(trim(get_config('filter_tex', 'pathdvips'), " '\""));
133 $command = "$pathdvips -E $dvi -o $ps";
134 if ($this->execute($command, $log )) {
135 return false;
138 // Run convert on document (.ps to .gif/.png) or run dvisvgm (.ps to .svg).
139 if ($background) {
140 $bg_opt = "-transparent \"$background\""; // Makes transparent background
141 } else {
142 $bg_opt = "";
144 if ($convertformat == 'svg') {
145 $pathdvisvgm = escapeshellarg(trim(get_config('filter_tex', 'pathdvisvgm'), " '\""));
146 $command = "$pathdvisvgm -E $ps -o $img";
147 } else {
148 $pathconvert = escapeshellarg(trim(get_config('filter_tex', 'pathconvert'), " '\""));
149 $command = "$pathconvert -density $density -trim $bg_opt $ps $img";
151 if ($this->execute($command, $log )) {
152 return false;
155 return $img;
159 * Delete files created in temporary area
160 * Don't forget to copy the final gif/png before calling this
161 * @param string $filename file base (no extension)
163 function clean_up( $filename ) {
164 global $CFG;
166 unlink( "{$this->temp_dir}/$filename.tex" );
167 unlink( "{$this->temp_dir}/$filename.dvi" );
168 unlink( "{$this->temp_dir}/$filename.ps" );
169 $convertformat = get_config('filter_tex', 'convertformat');
170 unlink( "{$this->temp_dir}/$filename.{$convertformat}" );
171 unlink( "{$this->temp_dir}/$filename.aux" );
172 unlink( "{$this->temp_dir}/$filename.log" );
173 return;