<?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('&lt;','<',$tex);
	$tex = str_replace('&gt;','>',$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";
                }
        }

}
?>