#!/usr/bin/env perl # gladtex: Reads a 'htex' file (html with LaTeX maths embedded in ) # and produces html with equations substituted by images. # Project homepage at http://folk.uio.no/martingu/gladtex/ # Copyright (C) 1999-2007 Martin G. Gulbrandsen # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # note: the utility 'eqn2img' should accompany this script, # and must be callable from this script. use IPC::Open2; use Cwd; use Getopt::Std; use Storable; #require 'getopts.pl'; -- replaced by GetOpt::Std module #require 'getcwd.pl'; -- replaced by Cwd module $img_dir = "."; # default values $dpi = 100; $supersample = 4; $format = "png"; $verbose = 0; $foreground = "000000"; $background = "A0A0A0"; $transparency = 1; $environment = "displaymath"; $preamble = " \\usepackage{amsmath} \\usepackage{amssymb} "; $usage = "gladtex version 1.1, Copyright (C) 1999-2007 Martin G. Gulbrandsen gladtex comes with ABSOLUTELY NO WARRANTY. This is free software, and you are welcome to redistribute it under certain conditions; see the file COPYING for details. Project homepage at http://folk.uio.no/martingu/gladtex/ Author email: Usage: gladtex [OPTION]... [FILE]... Convert htex file (HTML with LaTeX equations) to html with images -v print verbose information -f format store images in 'format' (png by default) -r dpi set resolution (size of images) to 'dpi' ($dpi by default) -s n set oversampling factor for antialiasing to 'n' ($supersample by default) -d path store image files in 'path' (current directory is default) -u url url to image files above (relative links are default) -p string add 'string' to LaTeX preamble (e.g. \\usepackage{...}) -e env embed LaTeX code in \\begin{env}..\\end{env} ($environment by default) -c colour set foreground RGB colour ($foreground by default) -b colour set background RGB colour ($background by default) -t turn transparency OFF Output files: *.html copy of input FILE(s), with .. tags properly replaced filename is same as input file, with the extension replaced eqn???.png equation images (png extension is example only, see -f option) Input files should not have .html extension, .htex is recommended. "; $| = 1; # flush output after every print, causes better feedback with -v flag $img_name = "eqn000"; # --- sub: rel_name --- # usage: rel_name $src, $dest; # $src and $dest should be absolute paths # returns: relative path to $dest, as seen from $src sub rel_name { my @src = split /\//, shift; my @dest = split /\//, shift; my $path; my $i = 0; # let $i = first level where $src and $dest doesn't match for($i=0; $i <= $#src and $i <= $#dest and $src[$i] eq $dest[$i]; $i++) {}; $path = "../" x ($#src - $i + 1); for(; defined $dest[$i]; $i++) { $path .= "$dest[$i]/"; } return $path; } # --- sub: full_name --- # usage: full_name $src, $dest # $src should be some absolute path # $dest may be relative (as seen from $src) or absolute # returns absolute path to $dest, as seen from $src (without trailing /) sub full_name { my $src = shift; my $dest = shift; # add trailing / if not present $dest .= "/" unless $dest =~ /\/$/; # if not absolute path, add $src $dest = $src . "/$dest" unless $dest =~ /^\//; # remove ./ $dest =~ s/\.\///g; # remove // while($dest =~ s{//}{/}g) {}; # remove ../ while($dest =~ s{/([^/]*/)\.\./}{$1}g) {}; # remove trailing / $dest =~ s/\/$//; return $dest; } # --- Parse command line options --- getopts('f:r:s:d:u:vtc:b:p:'); if($#ARGV < 0) { print $usage; print `eqn2img -f?`; # this prints list of supported formats exit; } $img_dir = $opt_d if defined $opt_d; $dpi = $opt_r if defined $opt_r; $supersample = $opt_s if defined $opt_s; $format = $opt_f if defined $opt_f; $verbose = $opt_v if defined $opt_v; $transparency = 0 if defined $opt_t; $preamble .= "$opt_p\n" if defined $opt_p; $foreground = $opt_c if defined $opt_c; $background = $opt_b if defined $opt_b; if(defined $opt_u) { $url = $opt_u; $url .= "/" unless $url =~ /\/$/; if(!defined $opt_d) { print "\nWarning: -u option present, but no -d\n\n"; } } $opt_t = 0; # just do something with $opt_t to avoid 'possible typo' warning # todo: add validization of options if($opt_d and !defined $url) { $img_dir = full_name(getcwd(), $img_dir); } # read in cached history if($opt_d and -r "$img_dir/gladtex.cache") { print "Retrieving cache\n" if $verbose; %history = %{retrieve("$img_dir/gladtex.cache")}; } # --- Process input files --- print "Processing ", $#ARGV + 1, " files\n" if $verbose; $startup_cwd = getcwd(); foreach $file (@ARGV) { ($directory, $basename, $extension) = $file =~ /(.*?)\/*([^\/]*?)\.([^\/]*)$/; $directory or $directory = "."; $basename or $basename = "noname"; $extension or $extension = "htex"; $extension eq "html" and die "Don't use .html extension, .htex is recommended."; $full_dir = full_name($startup_cwd, $directory); if(getcwd() ne $full_dir) { if(!$opt_d and defined %history) { print "Storing cache\n" if $verbose; store(\%history, "gladtex.cache"); undef %history; } chdir $full_dir; $img_name = "eqn000" if !$opt_d; } if(!$opt_d and !defined %history) { if(-r "gladtex.cache") { print "Retrieving cache\n" if $verbose; %history = %{retrieve("gladtex.cache")}; } # else { # %history = (); # } } open(INPUT, "$basename.$extension") or die "Cannot open $file"; open(OUTPUT, ">$basename.html") or die "Cannot open $basename.html"; print "\n$file -> $basename.html\n" if $verbose; for($start_line = 1; not eof INPUT; $start_line++) { $line = ; # search for tag (the s option is needed to avoid loosing linebreak at end of line) while($line =~ /(.*?)(.*)/is) { print OUTPUT $1; # everything before tag $options = $2; # anything between '' $line = $3; # the rest $this_preamble = $preamble; $this_foreground = $foreground; $this_background = $background; $this_environment = $environment; # scan options within tag # while($options =~ /\s*?(\S*?)=(\S*)/g) { # should whitespace be allowed around equal sign? while($options =~ /\s*?(\S*?)=\s*(\"(.*?)\"|\'(.*?)\'|(\S*))/g) { # should whitespace be allowed around equal sign? $key = $1; # only one of these will be defined $value = $3 if defined $3; # "value" $value = $4 if defined $4; # 'value' $value = $5 if defined $5; # value (no quotation marks) # is there a better way to scan for key/value pairs? foreach($key) { # may add more options here when needed.. /^preamble/i and $this_preamble .= "$value\n"; /^color/i and $this_foreground = $value; /^bgcolor/i and $this_background = $value; /^env/i and $this_environment = $value; } } $equation = ""; $end_line = $start_line; # read equation until is found while(not (($before, $after) = ($line =~ /(.*?)<\/eq>(.*)/is)) ) { $equation .= "$line\n"; if(eof INPUT) { print "Closing tag not found in equation started at line $start_line\n"; # todo: cleanup exit; } $line = ; $end_line++; } $equation .= $before; # everything before $line = $after; # everything after # strip whitespace: this makes 'history' stronger and removes linebreak # trouble (a paragraph can't end within $$..$$ in latex) $equation =~ s/\s+/ /g; print "Processing equation at line(s) $start_line to $end_line:\n" if $verbose; if($opt_u) { $img_src = $url; } else { if($opt_d) { $img_src = rel_name(getcwd(), $img_dir); } else { $img_src = ""; } } $eqn2img_opt = "-r $dpi -p '$this_preamble' -c $this_foreground -b $this_background -f $format -s $supersample " . ($transparency ? "" : "-t ") . ($verbose ? "-v " : ""); # --- process the latex code in $equation --- # recycle image if the same equation has appeared before with the # same options (colors etc.) if(defined $history{$equation} and $history{$equation}->{"opt"} eq $eqn2img_opt) { print "Reusing image\n" if $verbose; } else { while(-e "$img_dir/$img_name.$format") { $img_name++ }; # never overwrite an image print "$img_dir/$img_name: " if $verbose; $pid = open2(\*eqn2img_out, \*eqn2img_in, "eqn2img $eqn2img_opt -o $img_dir/$img_name.$format"); print eqn2img_in $equation; close eqn2img_in; $dimensions = ; waitpid $pid, 0; # close seems not to set $? when using open2, why is that? if($?) { print "Error processing equation starting at line $start_line:\n", $equation,"\n"; exit; } close eqn2img_out; print ", done.\n" if $verbose; $history{$equation}->{"opt"} = $eqn2img_opt; $history{$equation}->{"img"} = "$img_name.$format"; $history{$equation}->{"dim"} = $dimensions; } print OUTPUT "{"img"}."\" " .$history{$equation}->{"dim"}.">"; $start_line = $end_line; } print OUTPUT "$line"; } close(INPUT); close(OUTPUT); } # write history cache if($opt_d) { print "Storing cache\n" if $verbose; store(\%history , "$img_dir/gladtex.cache"); } else { print "Storing cache\n" if $verbose; store(\%history, "gladtex.cache"); }