@echo off c:\dir1\dir2\perl -x -S %0 %1 %2 %3 %4 %5 %6 %7 %8 %9 goto end #!/usr/bin/perl -w # WINDOWS users should rename this file "mathinhtml.bat" and supply # the correct path to perl on line 2. LINUX/UNIX users should # delete lines 1-3 and supply the correct path to perl on line 4. # 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; my $programname="mathinhtml063 (1-Apr-2003)"; ####################################################################### # This is where you tell mathinhtml the names of your programs. # If it's not in your path, you will need to include the full name. # (E.g. for Windows, my $PERL='c:\dir1\dir2\perl';) # If you don't have a program installed, give it the name ''. my $PERL='perl'; my $TEX='tex'; my $DVIPS='dvips'; my $GNUPLOT='gnuplot'; my $GHOSTSCRIPT='gs'; my $GPDIAGRAM='gpdiagram'; my $TEX2HTML='tex2html'; my $OVERSAMPLE=1; # Set to 1 for best screen quality. # Set to 2 or higher for better print quality. my $BGCOLOR='#FFFFFF'; # Default white background ####################################################################### # 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 => 'qx| $TEX -interaction=batchmode tempfile.1 |', action2 => 'qx| $DVIPS -E -q tempfile.dvi -o tempfile.ps |', action3 => 'unlink "tempfile.1", "tempfile.log", "tempfile.dvi"', output => 'ps', scale => 1, attrib => 'ALIGN="CENTER"' }; $rules{"EQ"}={%{$rules{"TEX"}}}; $rules{"EQ"}{"input1"}='\nopagenumbers \mag=1728 $$ _CONTENTS_ $$ \bye'; my $ps_setup="set terminal postscript eps enhanced color 24;". "set output 'tempfile.ps';"; $rules{"GNUPLOT"}={ input1 => $ps_setup.' _CONTENTS_ ', action1 => 'qx| $GNUPLOT tempfile.1 |', action2 => 'unlink "tempfile.1"', output => 'ps', scale => 1, attrib => 'ALIGN="TOP"' }; $rules{"GR"}={%{$rules{"GNUPLOT"}}}; $rules{"GR"}{"input1"}=$ps_setup.' set zeroaxis lt -1; set xtics axis;'. 'set ytics axis; set noborder; set nokey; _CONTENTS_ lw 2 '; $rules{"EQN"}={ input1 => '_CONTENTS_ ', action1 => 'qx| $PERL -S $TEX2HTML tempfile.1 tempfile.html |', action2 => 'unlink "tempfile.1"', output => 'html' }; $rules{"DIA"}={ input1 => ' _CONTENTS_ ', action1 => 'qx| $PERL -S $GPDIAGRAM tempfile.1 tempfile.ps |', action2 => 'unlink "tempfile.1"', output => 'ps', scale => 1, attrib => 'ALIGN="TOP"' }; ############################################################### # This section defines subroutines for manipulating png files my %crctable; # Remember table for crc checksums sub checksum { # Computes the CRC checksum used in png files my $crc=0xFFFFFFFF; foreach (split //, $_[0]){ my $n=( $crc ^ (unpack 'C', $_) ) & 0xFF; if (!$crctable{$n}){ my $c=$n; foreach (1..8) { $c= ($c & 1) ? 0xEDB88320^($c>>1) : ($c>>1) }; $crctable{$n}=$c; }; $crc=$crctable{$n} ^ ($crc>>8); }; return $crc ^ 0xFFFFFFFF; } sub createchunk { # Creates a valid png chunk from $string my $string=$_[0]; my $len=pack 'N', (length $string)-4; # Chunk type takes up 4 bytes my $crc=pack 'N', checksum $string; return $len.$string.$crc; } sub findchunk { # Finds the first chunk beginning with $type in $string my ($type, $string)=@_; my $t=length $type; my $len; for (my $k=8; $k; close FILE; return $contents; } sub ps2png { # Converts postscript to png my ($psfilename, $pngfilename, $resolution)=@_; (slurp $psfilename) =~ m/^%%BoundingBox: ([0-9]+) ([0-9]+) ([0-9]+) ([0-9]+)/m; my $translate="-$1 -$2 translate"; my $width=int($resolution*($3-$1)/72); my $height=int($resolution*($4-$2)/72); system "$GHOSTSCRIPT -dNOPAUSE -dBATCH -dQUIET -sDEVICE=png256 ". "-dPARANOIDSAFER -dTextAlphaBits=4 -dGraphicsAlphaBits=4 ". "-g${width}x$height -r$resolution -sOutputFile=$pngfilename ". "-c $translate -f $psfilename"; } sub modifypng { # Writes ... to $filename my ($filename, $key)=@_; my ($resolution, $bgcolor, $tagname, $contents)=split " ", $key, 4; # system "convert $filename $filename"; #compresses by factor of ~2 my $png=slurp $filename; my $width=unpack 'N', substr $png, 16, 4; my $height=unpack 'N', substr $png, 20, 4; substr($png, -12, 0)=createchunk "tEXtmathinhtml\0$key"; my ($k, $len, $palette)=findchunk("PLTE", $png); my $trans="tRNS"; my @bgcolor=map hex, $bgcolor =~ /.(..)(..)(..)/; my $newpalette="PLTE"; while ($palette =~ m/(...)/g) { $trans=$trans.($1 eq "\xFF\xFF\xFF" ? "\x00" : "\xFF"); my @color=unpack 'CCC', $1; foreach (0..2) { $color[$_]=int($color[$_]*$bgcolor[$_]/255) }; $newpalette.=pack 'CCC', @color; }; substr($png, $k, $len+12)=createchunk $newpalette; substr($png, $k+$len+12, 0)=createchunk $trans; open FILE, "> $filename"; binmode FILE; print FILE $png; close FILE; return ($width,$height); } my %index; sub createindex{ # Creates an index of pre-existing image files foreach my $filename (grep /\.png$/, @_) { my $imgstuff=slurp $filename; my ($dummy1, $dummy2, $key)=findchunk("tEXtmathinhtml\0",$imgstuff); if ($key) { my $w=unpack 'N', substr $imgstuff, 16, 4; my $h=unpack 'N', substr $imgstuff, 20, 4; # print "Indexing $filename\t${width}x$height\t$key\n"; $index{"$key"}={ filename=>$filename, width=>$w, height=>$h }; }; }; } sub translate { # Translates an element into its corresponding image/text my $key=$_[0]; my ($resolution, $bgcolor, $tagname, $contents)=split " ", $key, 4; 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"; for (my $i=1; defined $rules{$tagname}{"action$i"}; $i++){ eval $rules{$tagname}{"action$i"} ; }; if ($rules{$tagname}{"output"} eq "html") { my $html=slurp "tempfile.html"; unlink "tempfile.html"; return $html; } else { if ($rules{$tagname}{"output"} eq "ps"){ ps2png("tempfile.ps", "tempfile.png", $resolution); unlink "tempfile.ps"; }; if ($rules{$tagname}{"output"} =~ /^(ps|png)$/) { my ($width, $height)=modifypng("tempfile.png",$key); my $num=0; while (-s "IMG_$num.png") { $num++ }; my $imgname="IMG_$num.png"; rename "tempfile.png", $imgname; $index{$key}= {filename=>$imgname, width=>$width, height=>$height }; }; return "IMAGE"; } } my $tagnames=join '|', (keys %rules),"MIH"; # A list of defined tags sub replace { # Replaces a element by its translation my $qstr=q/(?:"[^"]*?"|'[^']*?')/; # Matches a quoted string my ($tagname, $attributes, $contents)= $_[0] =~ m|^<($tagnames)((?:\s+\w+=$qstr)*)\s*>(.*?)$|is; if ($tagname =~ /^mih$/i) { foreach (split " ", $attributes) { my ($name, $value)=split "="; $BGCOLOR=substr($value,1,-1) if ($name =~ /^bgcolor$/i); } return ""; } $contents =~ s/\s+/ /g; $contents =~ s/^ //; $contents =~ s/ $//; if ($rules{$tagname}{"output"} =~ /^(ps|png)$/){ my $scale= ($attributes =~s/scale=($qstr)//i) ? substr($1,1,-1) : $rules{$tagname}{"scale"}; my $bgcolor= ($attributes =~s/bgcolor=($qstr)//i) ? substr($1,1,-1) : $BGCOLOR; my $resolution= ($rules{$tagname}{"output"} eq "ps") ? int(72*$OVERSAMPLE*$scale) : 0; my $key="$resolution $bgcolor $tagname $contents"; translate($key) if (! exists $index{$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; }; $attributes=" SRC=\"$index{$key}{'filename'}\"". " WIDTH=\"".($index{$key}{'width'}/$OVERSAMPLE)."\"". " HEIGHT=\"".($index{$key}{'height'}/$OVERSAMPLE)."\"". " 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 ""; } elsif ($rules{$tagname}{"output"} eq "html") { my $key="0 0 $tagname $contents"; return translate($key) } } ################################################################# # This is the main executable. use File::Basename; print STDERR "\n$programname\nCopyright (C) 2003 Michael J Miller\n". "This program comes with absolutely no warranty.\n\n"; my ($inputfilename,$outputfilename)=@ARGV; die " SYNTAX: mathinhtml inputfile outputfile\n\n" if (!defined $outputfilename); my $input=slurp $inputfilename; my $outputdir=dirname $outputfilename; $outputfilename=basename $outputfilename; opendir DIR, $outputdir; my @files=readdir DIR; closedir DIR; chdir $outputdir; createindex @files; die "Please delete temporary file(s): @_\n" if (@_=grep/^tempfile\./, @files); for ($input) { s|.*?||igs; s||\n\n|i; } my @sections=$input =~ m/(.*?)(

|
|

  • ||.$)/igs; open(HTMLFILE, "> $outputfilename"); foreach (@sections){ s|<($tagnames)[\s>].*?|&replace($&)|iesg; print HTMLFILE "$_"; } close HTMLFILE; __END__ :end