#!/usr/bin/perl -w # mathinhtml is copyright (C) 2003 Michael J Miller # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License. This program # is distributed without any warranty (not even the implied warranty of # merchantability or fitness for a particular purpose). use strict; use File::Basename; my $programname="mathinhtml v0.60 (20-Feb-2003)"; ####################################################################### # This section defines the executables called by mathinhtml my $TEX="tex"; # "tex" for everyone my $DVIPS="dvips"; # "dvips" for everyone my $GNUPLOT="gnuplot"; # "gnuplot" for Linux; "pgnuplot" for Windows my $GHOSTSCRIPT="gs"; # "gs" for Linux; "gswin32c" for Windows ####################################################################### # This section establishes the rules by which mathinhtml translates # the contents of an element into the requested image/text. my %rules; $rules{"TEX"}={ input1 => "\\nopagenumbers _CONTENTS_ \\bye", action1 => "$TEX -interaction=batchmode tempfile.1", action2 => "$DVIPS -E -q tempfile.dvi -o tempfile.ps", density => 108, size => 108, attrib => 'ALIGN="CENTER"' }; $rules{"EQ"}={%{$rules{"TEX"}}}; $rules{"EQ"}{"input1"} ="\\nopagenumbers \$\$ _CONTENTS_ \$\$ \\bye"; my $ps_setup="set term postscript eps enhanced 24; set output 'tempfile.ps';"; $rules{"GNUPLOT"}={ input1 => "$ps_setup _CONTENTS_ ", action1 => "$GNUPLOT tempfile.1", density => 72, size => 72, attrib => 'ALIGN="TOP"' }; $rules{"GR"}={%{$rules{"GNUPLOT"}}}; $rules{"GR"}{"input1"}="$ps_setup; set zeroaxis; set xtics axis;". "set ytics axis; set noborder; set nokey; _CONTENTS_ "; $rules{"EQN"}={ input1 => "_CONTENTS_ ", action1 => "tex2html tempfile.1" }; my @tempfiles=qw/ tempfile.1 tempfile.dvi tempfile.log tempfile.ps /; ############################################################### # This section defines the subroutines "translate" (which translates # an element to its corresponding image/text) and "replace" (which # replaces an element by its translation). my %archive; # This hash catalogs those image files that have already been # created, so that existing images will not be recreated. my $tagnames=join '|', keys %rules; sub translate { my $key=$_[0]; my ($tagname, $contents)=split /\t/, $key; for (my $i=1; defined $rules{$tagname}{"input$i"}; $i++){ my $input=$rules{$tagname}{"input$i"}; $input =~ s/_CONTENTS_/$contents/g; open FILE, "> tempfile.$i"; print FILE "$input\n"; close FILE; } print STDERR "Translating $key\n"; my $output; for (my $i=1; defined $rules{$tagname}{"action$i"}; $i++){ $output=qx/ $rules{$tagname}{"action$i"} /; } if (-s "tempfile.ps"){ my $num=0; while (-s "IMG_$num.png") { $num++ }; my $imgname="IMG_$num.png"; my $psfile; open FILE, "< tempfile.ps"; $psfile=; close FILE; $psfile =~ m/^%%BoundingBox: ([0-9]+) ([0-9]+) ([0-9]+) ([0-9]+)/m; my $w=$3-$1; my $h=$4-$2; my $translate="-$1 -$2 translate"; my $density=$rules{$tagname}{"density"}; my $geometry=int($density*$w/72)."x".int($density*$h/72); system "$GHOSTSCRIPT -dNOPAUSE -dBATCH -dQUIET -sDEVICE=png256 ". "-dPARANOIDSAFER ". "-dTextAlphaBits=4 -dGraphicsAlphaBits=4 ". "-g$geometry -r$density -sOutputFile=$imgname ". "-c $translate -f tempfile.ps"; open FILE, "< $imgname"; seek (FILE, 16, 0); read (FILE, $_, 4); my $width=unpack 'N', $_; read (FILE, $_, 4); my $height=unpack 'N', $_; close FILE; $archive{$key}= {filename=>$imgname, width=>$width, height=>$height }; } else { $output =~ s/\s+/ /g; $archive{$key}=$output }; unlink @tempfiles; } sub replace { my $qstr=q/(?:"[^"]*?"|'[^']*?')/; # Matches a quoted string my ($tagname, $attributes, $contents)= $_[0] =~ m|^<($tagnames)((?:\s+\w+=$qstr)*)\s*>(.*?)$|is; $contents =~ s/\s+/ /g; my $key="$tagname\t$contents"; if (! exists $archive{$key}){ &translate($key) }; if (ref $archive{$key}){ for ($contents) { # replace "forbidden" html characters s/&/&/g; s//>/g; s/"/"/g; s/'/'/g; # replace backslash with space (may make TeX contents more readable) s/\\/ /g; }; my $sizequot=$rules{$tagname}{'size'}/$rules{$tagname}{'density'}; $attributes=" SRC=\"$archive{$key}{'filename'}\"". " WIDTH=\"".($archive{$key}{'width'}*$sizequot)."\"". " HEIGHT=\"".($archive{$key}{'height'}*$sizequot)."\"". " ALT=\"$contents\" TITLE=\"$contents\"". " $rules{$tagname}{'attrib'} $attributes"; while ($attributes =~ s/\s(\w+)=$qstr(.*?)\s\1=($qstr)/ $1=$3 $2 /is){}; for ($attributes){ s/\s+/ /g; s/ $// }; return ""; } else { return $archive{$key} }; } ############################################################## # This section defines the subroutines readarchive and writearchive, # which synchronize the hash %archive with the file archive.log. # The format of the file archive.log is tab-separated lines of # filename width height tagname contents output sub readarchive { if (open(ARCHIVELOG, "< archive.log")) { while ( ){ chomp; my ($filename, $width, $height, $tagname, $contents, $output)= split /\t/; if ($filename ne "" && -s $filename) { $archive{"$tagname\t$contents"}= { filename => $filename, width => $width, height => $height }; } elsif (defined($output)) { $archive{"$tagname\t$contents"}=$output }; }; }; close(ARCHIVELOG); } sub writearchive { open(ARCHIVELOG, "> archive.log"); foreach my $key (keys %archive){ if (ref $archive{$key}){ print ARCHIVELOG "$archive{$key}{'filename'}\t". "$archive{$key}{'width'}\t". "$archive{$key}{'height'}\t$key\n" } else { print ARCHIVELOG "\t\t\t$key\t$archive{$key}\n"; }; }; close ARCHIVELOG; } ################################################################# # This is the main executable. print STDERR "\n$programname\nCopyright (C) 2003 Michael J Miller\n". "This program comes with absolutely no warranty.\n\n"; chdir dirname $ARGV[0]; &readarchive; my $filename=basename $ARGV[0]; open(SOURCEFILE, "< $filename"); undef $/; $_=<>; close SOURCEFILE; s||\n\n|i; my @sections= m/(.*?)(

|
|

  • ||.$)/igs; $filename =~ s/\.mih$//; open(HTMLFILE, "> $filename.html"); foreach (@sections){ s|<($tagnames)[\s>].*?|&replace($&)|iesg; print HTMLFILE "$_"; } close HTMLFILE; &writearchive;