MDL-30070 message: Optimised search for users over multiple courses
[moodle.git] / filter / tex / latex.php
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
17          */
18         function latex() {
19             global $CFG;
21             // construct directory structure
22             $this->temp_dir = $CFG->tempdir . "/latex";
23             make_temp_directory('latex');
24         }
26         /**
27          * Accessor function for support_platform field.
28          * @return boolean value of supported_platform
29          */
30         function supported() {
31             return $this->supported_platform;
32         }
34         /**
35          * Turn the bit of TeX into a valid latex document
36          * @param string $forumula the TeX formula
37          * @param int $fontsize the font size
38          * @return string the latex document
39          */
40         function construct_latex_document( $formula, $fontsize=12 ) {
41             global $CFG;
43             $formula = filter_tex_sanitize_formula($formula);
45             // $fontsize don't affects to formula's size. $density can change size
46             $doc =  "\\documentclass[{$fontsize}pt]{article}\n";
47             $doc .=  $CFG->filter_tex_latexpreamble;
48             $doc .= "\\pagestyle{empty}\n";
49             $doc .= "\\begin{document}\n";
50 //dlnsk            $doc .= "$ {$formula} $\n";
51             if (preg_match("/^[[:space:]]*\\\\begin\\{(gather|align|alignat|multline).?\\}/i",$formula)) {
52                $doc .= "$formula\n";
53             } else {
54                $doc .= "$ {$formula} $\n";
55             }
56             $doc .= "\\end{document}\n";
57             return $doc;
58         }
60         /**
61          * execute an external command, with optional logging
62          * @param string $command command to execute
63          * @param file $log valid open file handle - log info will be written to this file
64          * @return return code from execution of command
65          */
66         function execute( $command, $log=null ) {
67             $output = array();
68             exec( $command, $output, $return_code );
69             if ($log) {
70                 fwrite( $log, "COMMAND: $command \n" );
71                 $outputs = implode( "\n", $output );
72                 fwrite( $log, "OUTPUT: $outputs \n" );
73                 fwrite( $log, "RETURN_CODE: $return_code\n " );
74             }
75             return $return_code;
76         }
78         /**
79          * Render TeX string into gif/png
80          * @param string $formula TeX formula
81          * @param string $filename base of filename for output (no extension)
82          * @param int $fontsize font size
83          * @param int $density density value for .ps to .gif/.png conversion
84          * @param string $background background color (e.g, #FFFFFF).
85          * @param file $log valid open file handle for optional logging (debugging only)
86          * @return bool true if successful
87          */
88         function render( $formula, $filename, $fontsize=12, $density=240, $background='', $log=null ) {
90             global $CFG;
92             // quick check - will this work?
93             if (empty($CFG->filter_tex_pathlatex)) {
94                 return false;
95             }
97             $doc = $this->construct_latex_document( $formula, $fontsize );
99             // construct some file paths
100             $tex = "{$this->temp_dir}/$filename.tex";
101             $dvi = "{$this->temp_dir}/$filename.dvi";
102             $ps  = "{$this->temp_dir}/$filename.ps";
103             $img = "{$this->temp_dir}/$filename.{$CFG->filter_tex_convertformat}";
105             // turn the latex doc into a .tex file in the temp area
106             $fh = fopen( $tex, 'w' );
107             fputs( $fh, $doc );
108             fclose( $fh );
110             // run latex on document
111             $command = "{$CFG->filter_tex_pathlatex} --interaction=nonstopmode --halt-on-error $tex";
112             chdir( $this->temp_dir );
113             if ($this->execute($command, $log)) { // It allways False on Windows
114 //                return false;
115             }
117             // run dvips (.dvi to .ps)
118             $command = "{$CFG->filter_tex_pathdvips} -E $dvi -o $ps";
119             if ($this->execute($command, $log )) {
120                 return false;
121             }
123             // run convert on document (.ps to .gif/.png)
124             if ($background) {
125                 $bg_opt = "-transparent \"$background\""; // Makes transparent background
126             } else {
127                 $bg_opt = "";
128             }
129             $command = "{$CFG->filter_tex_pathconvert} -density $density -trim $bg_opt $ps $img";
130             if ($this->execute($command, $log )) {
131                 return false;
132             }
134             return $img;
135         }
137         /**
138          * Delete files created in temporary area
139          * Don't forget to copy the final gif/png before calling this
140          * @param string $filename file base (no extension)
141          */
142         function clean_up( $filename ) {
143             global $CFG;
145             unlink( "{$this->temp_dir}/$filename.tex" );
146             unlink( "{$this->temp_dir}/$filename.dvi" );
147             unlink( "{$this->temp_dir}/$filename.ps" );
148             unlink( "{$this->temp_dir}/$filename.{$CFG->filter_tex_convertformat}" );
149             unlink( "{$this->temp_dir}/$filename.aux" );
150             unlink( "{$this->temp_dir}/$filename.log" );
151             return;
152         }
154     }