<?php /* Copyright 2005 R. van den Boomgaard (rein@visionconsultancy.nl), based on previous work of Schumacher et al. Replaced dvipng with combination of dvips and convert (from the ImageMagick toolkit). This is based on the same commands used in 'renderlatex'. Copyright 2004 J. Schumacher (0o0@gmx.net), based on code and suggestions by Christian Ridderström. and P. Michaud use: - {$ latex formula $}, for inline equations, like \( a+b \) in latex - {%label, latex formula%}, for \begin{math} like equations, EQ(label) can be used anywhere on the page as an anchor to the equation css: put usefull settings for these tags in your local.css or another appropriate place - span.mathRef for the anchor to the equation - img.formulaMath for equations with label, put a dotted line arround them or something - img.inlineMath, gues what, for inline equations - span.eqCount, for the little number behind labeled equations bugs: - where do the spaces in the name attribute of the anchor for the formulas come from, i had to remove the "" to make it work, not very nice - the whole ref() is implemented pretty bad i guess ... suggestions welcome - this definetly does not produce valid html - this propably isn't very safe requirements: - a complete latex installation - the dvipng programm (although image magik's convert could easily be used with a few changes to the code */ // variables $useMethod = "dvips-convert"; SDV( $dvipngPath, "/usr/bin/dvipng" ); SDV( $dvipsPath, "/usr/bin/dvips" ); SDV( $convertPath, "/usr/bin/convert" ); SDV($latexPath, "/usr/bin/latex"); SDV($ImgCacheDir,"pub/cache"); SDV($ImgCacheUrl,"$PubDirUrl/cache"); $eqArray; $eqCount = 0; $eqAbbrev = "Eq. "; // what text should be put in front of equation anchors $HTMLStylesFmt['inlineMath'] = " img.inlineMath { text-align: right; vertical-align: middle; margin-left: 0.5ex; margin-top: 0.2em; };"; // pattern to match #$DoubleBrackets['/\\{\\$(.*?)\\$\\}/e'] = "inline('$1')"; #$DoubleBrackets['/\\{\\%(.*?),(.*?)\\%\\}/e'] = "tex('$1', '$2')"; #$DoubleBrackets['/EQ\((.*?)\)/e'] = "ref('$1')"; Markup('{$','directives','/\\{\\$(.*?)\\$\\}/e',"inline('$1')"); // for inline latex Markup('{%','directives','/\\{\\%(.*?),(.*?)\\%\\}/e',"tex('$1','$2')"); // for formula with reference Markup('/EQ','directives','/EQ\((.*?)\)/e',"ref('$1')"); //for references to formulas function ref($replace) { global $eqArray, $eqAbbrev; $replace = trim($replace); for ($affe = 0; $affe < count($eqArray); $affe++) { // this is stupid, but i don't feel like thinking, could not get it to work with array_seach if ($eqArray[$affe] == $replace) { $affe += 1; return Keep("<a href=\"#$replace\"><span class=\"mathRef\">$eqAbbrev $affe</span></a>"); $affe -= 1; } } } function tex($label, $texFormula) { //variables global $ImgCacheUrl, $eqCount, $eqArray; // put the label into the array that holds all the labels ... :) ... god, that sounds stupid // increment the label counter $label = trim($label); $eqArray[$eqCount] = $label; $eqCount++; // create image name based on md5-sum of latex expression $imgN = md5($texFormula).".png"; $texFormula = trim($texFormula); makePng($texFormula, $imgN); // write html return Keep("<center><a name=$label><img class=\"formulaMath\" src=\"$ImgCacheUrl/$imgN\" alt=\"$texFormula\" /></a> <span class=\"eqCount\">($eqCount)</span></center>"); } function inline($texString) { // variables global $ImgCacheUrl; // create image name based on md5-sum of latex expression $imgN = md5($texString).".png"; $texString = trim($texString); makePng($texString, $imgN); // write html return Keep("<img class=\"inlineMath\" src=\"$ImgCacheUrl/$imgN\" alt=\"$texString\" />"); } // clean work.* stuff out off latex dir function cleanUp($patternStr) { foreach(glob($patternStr) as $fn) { unlink($fn); } } // create png function makePng($tex, $imgname) { global $useMethod, $dvipngPath,$dvipsPath, $convertPath, $latexPath, $ImgCacheDir; $tex = str_replace('<','<',$tex); $tex = str_replace('>','>',$tex); $tex = str_replace('$','\$',$tex); # Prevent user from leaving math mode $tex = str_replace('/','\slash{}',$tex); # Prevent user from open files... $tex = preg_replace('/{([^ ]+})/','{\nothing{}$1',$tex); # Obfuscate potential filenames // template for tex file $texString = "\documentclass[12pt]{article} \\usepackage{amssymb,amsmath,amscd,concmath} \\newcommand{\\nothing}{} \\pagestyle{empty} \\begin{document} \\begin{align*}$tex\\end{align*} \\end{document}"; // check if image already exists, if not create it if (!file_exists("$ImgCacheDir/$imgname")) { // create tex template touch("$ImgCacheDir/work.tex"); if ($fp = fopen("$ImgCacheDir/work.tex", "w+")) { fwrite($fp,$texString); //create dvi exec("cd $ImgCacheDir && $latexPath work.tex"); // create png switch ($useMethod) { case "dvips-convert": // first dvips then convert $cmd = "cd $ImgCacheDir && ".$dvipsPath." -D 400 -E work.dvi -o work.ps"; exec( $cmd ); //$cmd = "cd $ImgCacheDir && ".$convertPath." -density 100 -trim -transparent \"#FFFFFF\" work.ps ".$imgname; $cmd = "cd $ImgCacheDir && ".$convertPath." -density 100 -trim \"#FFFFFF\" work.ps ".$imgname; exec( $cmd ); break; case "dvipng": exec("cd $ImgCacheDir && $dvipngPath -T tight -bg Transparent -D 100 -o $imgname work.dvi"); break; } fclose($fp); // clean up cleanUp("$ImgCacheDir/work.*"); } else { echo "something has gone wrong, do you have correct permissions to $ImgCacheDir"; } } } ?>