]> CyberLeo.Net >> Repos - SourceForge/phpwiki.git/blob - lib/plugin/TeX2png.php
getName should not translate
[SourceForge/phpwiki.git] / lib / plugin / TeX2png.php
1 <?php
2
3 /*
4  * Copyright (C) Copyright 2004 Pierrick Meignen
5  *
6  * This file is part of PhpWiki.
7  *
8  * PhpWiki is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * PhpWiki is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License along
19  * with PhpWiki; if not, write to the Free Software Foundation, Inc.,
20  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21  */
22
23 /**
24  * This is a simple version of the original TexToPng plugin which uses
25  * the powerful plugincached mechanism.
26  * TeX2png uses its own much simplier static cache in images/tex.
27  *
28  * @author: Pierrick Meignen
29  * TODO: use url helpers, windows fixes
30  *       use a better imagepath
31  */
32
33 // needs latex
34 // LaTeX2HTML ftp://ftp.dante.de/tex-archive/support/latex2html
35
36 class WikiPlugin_TeX2png
37     extends WikiPlugin
38 {
39     public $imagepath = 'images/tex';
40     public $latexbin = '/usr/bin/latex';
41     public $dvipsbin = '/usr/bin/dvips';
42     public $pstoimgbin = '/usr/bin/pstoimg';
43
44     function getDescription()
45     {
46         return _("Convert Tex mathematicals expressions to cached PNG files. This is for small text.");
47     }
48
49     function getDefaultArguments()
50     {
51         return array('text' => "$$(a + b)^2 = a^2 + 2 ab + b^2$$");
52     }
53
54     function parseArgStr($argstr)
55     {
56         // modified from WikiPlugin.php
57         $arg_p = '\w+';
58         $op_p = '(?:\|\|)?=';
59         $word_p = '\S+';
60         $opt_ws = '\s*';
61         $qq_p = '" ( (?:[^"\\\\]|\\\\.)* ) "';
62         //"<--kludge for brain-dead syntax coloring
63         $q_p = "' ( (?:[^'\\\\]|\\\\.)* ) '";
64         $gt_p = "_\\( $opt_ws $qq_p $opt_ws \\)";
65         $argspec_p = "($arg_p) $opt_ws ($op_p) $opt_ws (?: $qq_p|$q_p|$gt_p|($word_p))";
66
67         $args = array();
68         $defaults = array();
69
70         while (preg_match("/^$opt_ws $argspec_p $opt_ws/x", $argstr, $m)) {
71             @ list(, $arg, $op, $qq_val, $q_val, $gt_val, $word_val) = $m;
72             $argstr = substr($argstr, strlen($m[0]));
73
74             // Remove quotes from string values.
75             if ($qq_val)
76                 // we don't remove backslashes in tex formulas
77                 // $val = stripslashes($qq_val);
78                 $val = $qq_val;
79             elseif ($q_val)
80                 $val = stripslashes($q_val); elseif ($gt_val)
81                 $val = _(stripslashes($gt_val)); else
82                 $val = $word_val;
83
84             if ($op == '=') {
85                 $args[$arg] = $val;
86             } else {
87                 // NOTE: This does work for multiple args. Use the
88                 // separator character defined in your webserver
89                 // configuration, usually & or &amp; (See
90                 // http://www.htmlhelp.com/faq/cgifaq.4.html)
91                 // e.g. <plugin RecentChanges days||=1 show_all||=0 show_minor||=0>
92                 // url: RecentChanges?days=1&show_all=1&show_minor=0
93                 assert($op == '||=');
94                 $defaults[$arg] = $val;
95             }
96         }
97
98         if ($argstr) {
99             $this->handle_plugin_args_cruft($argstr, $args);
100         }
101
102         return array($args, $defaults);
103     }
104
105     function createTexFile($texfile, $text)
106     {
107         // this is the small latex file
108         // which contains only the mathematical
109         // expression
110         $fp = fopen($texfile, 'w');
111         $str = "\documentclass{article}\n";
112         $str .= "\usepackage{amsfonts}\n";
113         $str .= "\usepackage{amssymb}\n";
114         // Here tou can add some package in order
115         // to produce more sophisticated output
116         $str .= "\pagestyle{empty}\n";
117         $str .= "\begin{document}\n";
118         $str .= $text . "\n";
119         $str .= "\end{document}";
120         fwrite($fp, $str);
121         fclose($fp);
122         return 0;
123     }
124
125     function createPngFile($imagepath, $imagename)
126     {
127         // to create dvi file from the latex file
128         $commandes = $this->latexbin . " temp.tex;";
129         exec("cd $imagepath;$commandes");
130         // to create png file from the dvi file
131         // there is no option but it is possible
132         // to add one (scale for example)
133         if (file_exists("$imagepath/temp.dvi")) {
134             $commandes = $this->dvipsbin . " temp.dvi -o temp.ps;";
135             $commandes .= $this->pstoimgbin . " -type png -margins 0,0 ";
136             $commandes .= "-crop a -geometry 600x300 ";
137             $commandes .= "-aaliastext -color 1 -scale 1.5 ";
138             $commandes .= "temp.ps -o " . $imagename;
139             exec("cd $imagepath;$commandes");
140             unlink("$imagepath/temp.dvi");
141             unlink("$imagepath/temp.ps");
142         } else
143             echo _(" (syntax error for latex) ");
144         // to clean the directory
145         unlink("$imagepath/temp.tex");
146         unlink("$imagepath/temp.aux");
147         unlink("$imagepath/temp.log");
148         return 0;
149     }
150
151     function isMathExp(&$text)
152     {
153         // this function returns
154         // 0 : text is too long or not a mathematical expression
155         // 1 : text is $xxxxxx$ hence in line
156         // 2 : text is $$xxxx$$ hence centered
157         $last = strlen($text) - 1;
158         if ($last >= 250) {
159             $text = "Too long !";
160             return 0;
161         } elseif ($last <= 1 || strpos($text, '$') != 0) {
162             return 0;
163         } elseif (strpos($text, '$', 1) == $last)
164             return 1; elseif ($last > 3 &&
165             strpos($text, '$', 1) == 1 &&
166             strpos($text, '$', 2) == $last - 1
167         )
168             return 2;
169         return 0;
170     }
171
172     function tex2png($text)
173     {
174         // the name of the png cached file
175         $imagename = md5($text) . ".png";
176         $url = $this->imagepath . "/$imagename";
177
178         if (!file_exists($url)) {
179             if (is_writable($this->imagepath)) {
180                 $texfile = $this->imagepath . "/temp.tex";
181                 $this->createTexFile($texfile, $text);
182                 $this->createPngFile($this->imagepath, $imagename);
183             } else {
184                 $error_html = _("TeX imagepath not writable.");
185                 trigger_error($error_html, E_USER_NOTICE);
186             }
187         }
188
189         // there is always something in the html page
190         // even if the tex directory doesn't exist
191         // or mathematical expression is wrong
192         switch ($this->isMathExp($text)) {
193             case 0: // not a mathematical expression
194                 $html = HTML::tt(array('class' => 'tex',
195                     'style' => 'color:red;'), $text);
196                 break;
197             case 1: // an inlined mathematical expression
198                 $html = HTML::img(array('class' => 'tex',
199                     'src' => $url,
200                     'alt' => $text));
201                 break;
202             case 2: // mathematical expression on separate line
203                 $html = HTML::img(array('class' => 'tex',
204                     'src' => $url,
205                     'alt' => $text));
206                 $html = HTML::div(array('align' => 'center'), $html);
207                 break;
208             default:
209                 break;
210         }
211
212         return $html;
213     }
214
215     function run($dbi, $argstr, &$request, $basepage)
216     {
217         // from text2png.php
218         if ((function_exists('ImageTypes') and (ImageTypes() & IMG_PNG))
219             or function_exists("ImagePNG")
220         ) {
221             // we have gd & png so go ahead.
222             extract($this->getArgs($argstr, $request));
223             return $this->tex2png($text);
224         } else {
225             // we don't have png and/or gd.
226             $error_html = _("Sorry, this version of PHP cannot create PNG image files.");
227             $link = "http://www.php.net/manual/pl/ref.image.php";
228             $error_html .= sprintf(_("See %s"), $link) . ".";
229             trigger_error($error_html, E_USER_NOTICE);
230             return HTML::p($error_html);
231         }
232     }
233 }
234
235 // Local Variables:
236 // mode: php
237 // tab-width: 8
238 // c-basic-offset: 4
239 // c-hanging-comment-ender-p: nil
240 // indent-tabs-mode: nil
241 // End: