This code takes a TeX or LaTeX math expression and converts it into a Tk image suitable for placing in any suitable widget. This technique is ideal for complex documentation where you don't want to maintain a separate set of image files, but is not really fast enough for interactive use (unless your machine is much faster than mine.)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 | namespace eval MathToImg {
image create photo MathToImgHelperImage
set tmpdir "/tmp"; # configure for platforms!
# What LaTeX size should we format at? This looks good on my workstation
set latexSize huge; # No backslash!
# Commands
set latexCommand "latex '\\nonstopmode\\input{%s.tex}'"
set dvipsCommand "dvips -E -q -o %s.eps %s.dvi"
set gsCommand "gs -q -dNOPAUSE -dSAFER -sDEVICE=ppmraw -sOutputFile=%s.ppm %s.eps"
# Regular expression for finding bounding box
set BBre {^%%BoundingBox: ([0-9]+) ([0-9]+) ([0-9]+) ([0-9]+) *$}
proc external cmd {
exec sh -c $cmd 2>@stderr </dev/null
}
proc mathToImg {latex {packages {}}} {
# Keep ourselves current-dir neutral
set cwd [pwd]
cd $::MathToImg::tmpdir
# Put a wrapper round the supplied LaTeX source
set latexSource "\\documentclass{article}\n"
if {[llength $packages]} {
# Add needed packages, converting Tcl list to comma-ed list
append latexSource "\\usepackage{" [join $packages ,] "}"
}
append latexSource "\\begin{document} \\$::MathToImg::latexSize \\pagestyle{empty} \\begin{displaymath}\n% USER CODE START\n"
append latexSource $latex "\n% USER CODE END\n"
append latexSource "\\end{displaymath} \\end{document}\n"
set basename [file tail [file rootname $::argv0]]_mathToImg_[pid]
set f [open $basename.tex w]
puts -nonewline $f $latexSource
close $f
# LaTeX -> DVI
external [format $::MathToImg::latexCommand $basename]
# DVI -> EPS
external [format $::MathToImg::dvipsCommand $basename $basename]
# Grok out the size, which we need later...
set f [open $basename.eps r]
while {![eof $f]} {
gets $f line
if {[regexp $::MathToImg::BBre $line ? x1 y1 x2 y2]} {
break
}
}
close $f
# EPS -> PPM
external [format $::MathToImg::gsCommand $basename $basename]
# Make the image - we can't go direct as we need the size of
# the image to handle the cropping correctly.
set img [image create photo -height [expr {$y2-$y1}] -width [expr {$x2-$x1}]]
# PS has (0,0) in bottom left, Tk in top left
MathToImgHelperImage read $basename.ppm
set h [image height MathToImgHelperImage]
$img copy MathToImgHelperImage -from $x1 [expr {$h-$y1}] $x2 [expr {$h-$y2}]
MathToImgHelperImage blank; # Ditch the data
# Try to clean up after ourselves!
catch {eval file delete [glob $basename.*]}
cd $cwd
return $img
}
namespace export mathToImg
}
namespace import MathToImg::*
|
Sample use: pack [label .l -image [mathToImg {\sum_{i=1}^9 x_i}]]
Requires: a UNIX with LaTeX, DVIPS and GhostScript installed. Can use rather a lot of intermediate memory, so solutions involving the PS command 'setpagedevice' would be welcome upgrades...