Parent Directory
|
Revision Log
removed unneeded code from WeBWorK::PG, WeBWorK::PG::ImageGenerator::add now supports both add($in_delim) and add($in, $mode). -sam
1 ################################################################################ 2 # WeBWorK mod_perl (c) 2000-2002 WeBWorK Project 3 # $Id$ 4 ################################################################################ 5 6 package WeBWorK::PG::ImageGenerator; 7 8 =head1 NAME 9 10 WeBWorK::PG::ImageGenerator - create an object for holding bits of math for 11 LaTeX, and then to process them all at once. 12 13 =head1 SYNPOSIS 14 15 FIXME: add this 16 17 =cut 18 19 use strict; 20 use warnings; 21 use WeBWorK::Utils qw(readDirectory makeTempDirectory removeTempDirectory); 22 23 use constant PREAMBLE => <<'EOF'; 24 \documentclass[12pt]{article} 25 \nonstopmode 26 \usepackage{amsmath,amsfonts,amssymb} 27 \def\gt{>} 28 \def\lt{<} 29 \usepackage[active,textmath,displaymath]{preview} 30 \begin{document} 31 EOF 32 use constant POSTAMBLE => <<'EOF'; 33 \end{document} 34 EOF 35 use constant DVIPNG_ARGS => join " ", qw( 36 -x4000.5 37 -bgTransparent 38 -Q6 39 -mode toshiba 40 -D180 41 ); 42 43 =head1 METHODS 44 45 =over 46 47 =item new 48 49 Returns a new ImageGenerator object. <C%options> must contain the following entries: 50 51 tempDir => directory for storing temporary files (non-web accessible) 52 dir => directory for resulting files 53 url => url to directory for resulting files 54 basename => base name for image files 55 latex => path to latex binary 56 dvipng => path to dvipng binary 57 58 =cut 59 60 sub new { 61 my ($invocant, %options) = @_; 62 my $class = ref $invocant || $invocant; 63 my $self = { 64 strings => [], 65 %options, 66 }; 67 68 bless $self, $class; 69 } 70 71 =item add($string, $mode) 72 73 Adds the equation in C<$string> to the object. C<$mode> can be "display" or "inline". If 74 not specified, "inline" is assumed. Returns the proper HTML tag for displaying the image. 75 76 =cut 77 78 sub add { 79 my ($self, $string, $mode) = @_; 80 81 my $strings = $self->{strings}; 82 my $dir = $self->{dir}; 83 my $url = $self->{url}; 84 my $basename = $self->{basename}; 85 86 # if the string came in with delimiters, chop them off and set the mode 87 # based on whether they were \[ .. \] or \( ... \). this means that if 88 # the string has delimiters, the mode *argument* is ignored. 89 if ($string =~ s/^\\\[(.*)\\\]$/$1/) { 90 $mode = "display"; 91 } elsif ($string =~ s/^\\\((.*)\\\)$/$1/) { 92 $mode = "inline"; 93 } 94 # otherwise, leave the string and the mode alone. 95 96 my $imageNum = @$strings + 1; 97 my $imageURL = "$url/$basename.$imageNum.png"; 98 my $imageTag = "<img src=\"$imageURL\" align=\"middle\" alt=\"$string\">"; 99 100 if ($mode eq "display") { 101 push @$strings, '\(\displaystyle{' . $string . '}\)'; 102 return " <div align=\"center\">$imageTag</div> "; 103 } else { 104 push @$strings, '\(' . $string . '\)'; 105 return " $imageTag "; 106 } 107 } 108 109 =item render(%options) 110 111 Uses LaTeX and dvipng to render the equations stored in the object. If the key "mtime" in 112 C<%options> is given, it will be interpreted as a unix date and compared with the 113 modification date on any existing copy of the first image to be generated. It is 114 recommended that the modification time of the source file from which the equations 115 originate be used for this value. If the key "refresh" in C<%options> is true, images 116 will be regenerated regardless of when they were last modified. 117 118 =cut 119 120 sub render { 121 my ($self, %options) = @_; 122 123 my $tempDir = $self->{tempDir}; 124 my $dir = $self->{dir}; 125 my $basename = $self->{basename}; 126 my $latex = $self->{latex}; 127 my $dvipng = $self->{dvipng}; 128 my $strings = $self->{strings}; 129 130 my $mtime = $options{mtime}; 131 my $refresh = not defined $mtime || $options{refresh}; 132 # must refresh if no mtime is given 133 134 return unless @$strings; # Don't run latex if there are no images to generate 135 136 unless ($refresh) { 137 my $firstImage = "$dir/$basename.1.png"; 138 if (-e $firstImage) { 139 # return if first image newer than $mtime 140 return if (stat $firstImage)[9] >= $mtime; 141 } 142 } 143 144 # create temporary directory in which to do TeX processing 145 my $wd = makeTempDirectory($tempDir, "ImageGenerator"); 146 147 # store equations in a tex file 148 my $texFile = "$wd/equation.tex"; 149 open my $tex, ">", $texFile 150 or die "failed to open file $texFile for writing: $!"; 151 print $tex PREAMBLE; 152 print $tex "$_\n" foreach @$strings; 153 print $tex POSTAMBLE; 154 close $tex; 155 156 # call LaTeX 157 my $latexCommand = "cd $wd && $latex equation > latex.out 2> latex.err"; 158 my $latexStatus = system $latexCommand; 159 warn "$latexCommand returned non-zero status $latexStatus: $!" 160 if $latexStatus; 161 warn "$latexCommand failed to generate a DVI file" 162 unless -e "$wd/equation.dvi"; 163 164 # call dvipng 165 my $dvipngCommand = "cd $wd && $dvipng " . DVIPNG_ARGS . " equation > dvipng.out 2> dvipng.err"; 166 my $dvipngStatus = system $dvipngCommand; 167 #warn "$dvipngCommand returned non-zero status $dvipngStatus: $!" 168 # if $dvipngStatus; 169 170 # move/rename images 171 foreach my $image (readDirectory($wd)) { 172 # only work on equation#.png files 173 next unless $image =~ m/^equation(\d+)\.png$/; 174 175 # get image number from above match 176 my $imageNum = $1; 177 178 # move/rename image 179 my $mvCommand = "cd $wd && /bin/mv $wd/$image $dir/$basename.$imageNum.png"; 180 my $mvStatus = system $mvCommand; 181 warn "$mvCommand returned non-zero status $mvStatus: $!" 182 if $mvStatus; 183 } 184 185 # remove temporary directory (and its contents) 186 removeTempDirectory($wd); 187 } 188 189 1; 190 191 __END__ 192 193 ################################################################################ 194 # OLD VERSIONS OF SUBROUTINES 195 ################################################################################ 196 197 198 sub getCount { 199 my $self = shift; 200 return $self->{count}; 201 } 202 203 sub tmpurl { 204 my $self = shift; 205 return "$self->{tmpURLstart}/$self->{filenamestart}"; 206 } 207 208 sub initialize { 209 my ($self, $envir) = @_; 210 211 my $problemnum = $envir->{'probNum'}; 212 my $studname = $envir->{'studentLogin'}; 213 my $psvn = $envir->{'psvn'}; 214 my $setname = $envir->{'setNumber'}; 215 my $tmpURLstart = $envir->{'tempURL'}; 216 217 my $path=main::surePathToTmpFile(main::convertPath("png/$setname/$psvn/foo")); 218 $path =~ s/foo$//; # remove final foo 219 220 $self->{sourceFile} = $envir->{templateDirectory} . "/" . $envir->{fileName}; 221 $self->{tmpURLstart} = $tmpURLstart."png/$setname/$psvn"; 222 $self->{tmppath}=$path; 223 $self->{filenamestart}="$studname-prob${problemnum}image"; 224 } 225 226 # Add another string to list to be LaTeX'ed 227 # return the tag 228 sub add { 229 my $self = shift; 230 my $newstr = shift; 231 my $tag = $newstr; 232 $self->{count}++; 233 my $tempURL= $self->tmpurl()."$self->{count}.png"; 234 235 if ($tag =~ /^\\\(/) { 236 $tag =~ s|^\\\( *||; 237 $tag =~ s|\\\)$||; 238 $tag = qq!<img src="$tempURL" align="middle" alt="$tag">!; 239 } else { 240 # Displayed math comes in with \[ stuff \]. To get a good 241 # bounding box through preview, we change that to \( \displaystyle{ 242 # stuff } \), and then center the resulting image 243 $tag =~ s|^\\\[ *||; 244 $tag =~ s|\\\]$||; 245 $newstr = '\(\displaystyle{'.$tag.'}\)'; 246 $tag = qq!<div align="center"><img src="$tempURL" align="middle" alt="$tag"></div>!; 247 } 248 249 push @{$self->{latexlines}}, $newstr; 250 return $tag; 251 } 252 253 sub render { 254 my $self = shift; 255 my %opts = @_; 256 257 # Don't run latex if there are no images 258 if($self->{count}==0) { 259 return; 260 } 261 262 my $refreshMe = 0; 263 if (defined($opts{refresh}) and (($opts{refresh} eq "yes") or ($opts{refresh} == 1))) { 264 $refreshMe = 1; 265 } 266 267 #$refreshMe = 1; # Uncomment for testing 268 my $latexfilenamebase = $self->{tmppath} . $self->{filenamestart}; 269 270 my $sourcePath = $self->{sourceFile}; 271 my $tempFile = "${latexfilenamebase}" . $self->{count} . ".png"; # last image 272 273 if ($refreshMe or not -e $tempFile or (stat $sourcePath)[9] > (stat $tempFile)[9]) { 274 # image file doesn't exist, or source file is newer then image file 275 # or we just want new images produced 276 277 #my $old_cdir = `pwd`; # cd for running latex 278 #chomp($old_cdir); 279 chdir($self->{tmppath}) 280 || warn "Could not move into temporary directory $self->{tmppath}"; 281 282 if (-e "$latexfilenamebase.tex") { 283 unlink("$latexfilenamebase.tex") || 284 warn "Could not delete old LaTeX file"; 285 } 286 287 local *LATEXME; 288 open(LATEXME,">$latexfilenamebase.tex") || warn "Cannot create temporary tex file"; 289 print LATEXME <<'EOT'; 290 \documentclass[12pt]{article} 291 \nonstopmode 292 \usepackage{amsmath,amsfonts,amssymb} 293 \def\gt{>} 294 \def\lt{<} 295 296 \usepackage[active,textmath,displaymath]{preview} 297 \begin{document} 298 EOT 299 300 my $j; 301 for $j (@{$self->{latexlines}}) { 302 print LATEXME "\n$j\n"; 303 } 304 305 print LATEXME '\end{document}'."\n"; 306 close(LATEXME); 307 308 chmod(0666, "$latexfilenamebase.tex") || warn "Could not change permissions on $latexfilenamebase.tex"; 309 310 my $error_log = '/dev/null'; ## by default do not log error messages 311 $error_log = &Global::getErrorLog if $Global::imageDebugMode; 312 313 $ENV{PATH} .= "$Global::extendedPath"; 314 my $dvipng_res = int($Global::dvipngScaling * 1000+0.5); 315 my $cmdout=""; 316 317 # remove any old files using this name 318 unlink("$self->{filenamestart}.dvi","$self->{filenamestart}.log", 319 "$self->{filenamestart}.aux","missfont.log"); 320 321 $cmdout=system("$Global::externalLatexPath $self->{filenamestart}.tex >>$error_log 2>>$error_log"); 322 warn "$Global::externalLatexPath $self->{filenamestart}.tex >>$error_log 2>>$error_log -- FAILED in ImageGenerator returned $cmdout" if $cmdout; 323 324 $cmdout=system("$Global::externalDvipngPath -x$dvipng_res -bgTransparent -Q$Global::dvipngShrinkFactor -mode $Global::dvipngMode -D$Global::dvipngDPI $self->{filenamestart}.dvi >>$error_log 2>>$error_log"); 325 warn "$Global::externalDvipngPath -x$dvipng_res -bgTransparent -Q$Global::dvipngShrinkFactor -mode $Global::dvipngMode -D$Global::dvipngDPI $self->{filenamestart}.dvi >>$error_log 2>>$error_log -- FAILED in ImageGenerator.pm returned $cmdout" if $cmdout !=256; 326 327 unless ($Global::imageDebugMode) { 328 unlink("$self->{filenamestart}.dvi","$self->{filenamestart}.log", 329 "$self->{filenamestart}.tex", 330 "$self->{filenamestart}.aux" 331 ); 332 } 333 #chdir($old_cdir); 334 } 335 } 336 337 1;
| aubreyja at gmail dot com | ViewVC Help |
| Powered by ViewVC 1.0.9 |