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