164 lines
5.1 KiB
Python
164 lines
5.1 KiB
Python
|
import py
|
||
|
|
||
|
from py.__.process.cmdexec import ExecutionFailed
|
||
|
# utility functions to convert between various formats
|
||
|
|
||
|
format_to_dotargument = {"png": "png",
|
||
|
"eps": "ps",
|
||
|
"ps": "ps",
|
||
|
"pdf": "ps",
|
||
|
}
|
||
|
|
||
|
def ps2eps(ps):
|
||
|
# XXX write a pure python version
|
||
|
if not py.path.local.sysfind("ps2epsi") and \
|
||
|
not py.path.local.sysfind("ps2eps"):
|
||
|
raise SystemExit("neither ps2eps nor ps2epsi found")
|
||
|
try:
|
||
|
eps = ps.new(ext=".eps")
|
||
|
py.process.cmdexec('ps2epsi "%s" "%s"' % (ps, eps))
|
||
|
except ExecutionFailed:
|
||
|
py.process.cmdexec('ps2eps -l -f "%s"' % ps)
|
||
|
|
||
|
def ps2pdf(ps, compat_level="1.2"):
|
||
|
if not py.path.local.sysfind("gs"):
|
||
|
raise SystemExit("ERROR: gs not found")
|
||
|
pdf = ps.new(ext=".pdf")
|
||
|
options = dict(OPTIONS="-dSAFER -dCompatibilityLevel=%s" % compat_level,
|
||
|
infile=ps, outfile=pdf)
|
||
|
cmd = ('gs %(OPTIONS)s -q -dNOPAUSE -dBATCH -sDEVICE=pdfwrite '
|
||
|
'"-sOutputFile=%(outfile)s" %(OPTIONS)s -c .setpdfwrite '
|
||
|
'-f "%(infile)s"') % options
|
||
|
py.process.cmdexec(cmd)
|
||
|
return pdf
|
||
|
|
||
|
def eps2pdf(eps):
|
||
|
# XXX write a pure python version
|
||
|
if not py.path.local.sysfind("epstopdf"):
|
||
|
raise SystemExit("ERROR: epstopdf not found")
|
||
|
py.process.cmdexec('epstopdf "%s"' % eps)
|
||
|
|
||
|
def dvi2eps(dvi, dest=None):
|
||
|
if dest is None:
|
||
|
dest = eps.new(ext=".eps")
|
||
|
command = 'dvips -q -E -n 1 -D 600 -p 1 -o "%s" "%s"' % (dest, dvi)
|
||
|
if not py.path.local.sysfind("dvips"):
|
||
|
raise SystemExit("ERROR: dvips not found")
|
||
|
py.process.cmdexec(command)
|
||
|
|
||
|
def convert_dot(fn, new_extension):
|
||
|
if not py.path.local.sysfind("dot"):
|
||
|
raise SystemExit("ERROR: dot not found")
|
||
|
result = fn.new(ext=new_extension)
|
||
|
print result
|
||
|
arg = "-T%s" % (format_to_dotargument[new_extension], )
|
||
|
py.std.os.system('dot "%s" "%s" > "%s"' % (arg, fn, result))
|
||
|
if new_extension == "eps":
|
||
|
ps = result.new(ext="ps")
|
||
|
result.move(ps)
|
||
|
ps2eps(ps)
|
||
|
ps.remove()
|
||
|
elif new_extension == "pdf":
|
||
|
# convert to eps file first, to get the bounding box right
|
||
|
eps = result.new(ext="eps")
|
||
|
ps = result.new(ext="ps")
|
||
|
result.move(ps)
|
||
|
ps2eps(ps)
|
||
|
eps2pdf(eps)
|
||
|
ps.remove()
|
||
|
eps.remove()
|
||
|
return result
|
||
|
|
||
|
|
||
|
class latexformula2png(object):
|
||
|
def __init__(self, formula, dest, temp=None):
|
||
|
self.formula = formula
|
||
|
try:
|
||
|
import Image
|
||
|
self.Image = Image
|
||
|
self.scale = 2 # create a larger image
|
||
|
self.upscale = 5 # create the image upscale times larger, then scale it down
|
||
|
except ImportError:
|
||
|
self.scale = 2
|
||
|
self.upscale = 1
|
||
|
self.Image = None
|
||
|
self.output_format = ('pngmono', 'pnggray', 'pngalpha')[2]
|
||
|
if temp is None:
|
||
|
temp = py.test.ensuretemp("latexformula")
|
||
|
self.temp = temp
|
||
|
self.latex = self.temp.join('formula.tex')
|
||
|
self.dvi = self.temp.join('formula.dvi')
|
||
|
self.eps = self.temp.join('formula.eps')
|
||
|
self.png = self.temp.join('formula.png')
|
||
|
self.saveas(dest)
|
||
|
|
||
|
def saveas(self, dest):
|
||
|
self.gen_latex()
|
||
|
self.gen_dvi()
|
||
|
dvi2eps(self.dvi, self.eps)
|
||
|
self.gen_png()
|
||
|
self.scale_image()
|
||
|
self.png.copy(dest)
|
||
|
|
||
|
def gen_latex(self):
|
||
|
self.latex.write ("""
|
||
|
\\documentclass{article}
|
||
|
\\pagestyle{empty}
|
||
|
\\begin{document}
|
||
|
|
||
|
%s
|
||
|
\\pagebreak
|
||
|
|
||
|
\\end{document}
|
||
|
""" % (self.formula))
|
||
|
|
||
|
def gen_dvi(self):
|
||
|
origdir = py.path.local()
|
||
|
self.temp.chdir()
|
||
|
py.process.cmdexec('latex "%s"' % (self.latex))
|
||
|
origdir.chdir()
|
||
|
|
||
|
def gen_png(self):
|
||
|
tempdir = py.path.local.mkdtemp()
|
||
|
|
||
|
re_bbox = py.std.re.compile('%%BoundingBox:\s*(\d+) (\d+) (\d+) (\d+)')
|
||
|
eps = self.eps.read()
|
||
|
x1, y1, x2, y2 = [int(i) for i in re_bbox.search(eps).groups()]
|
||
|
X = x2 - x1 + 2
|
||
|
Y = y2 - y1 + 2
|
||
|
mx = -x1
|
||
|
my = -y1
|
||
|
ps = self.temp.join('temp.ps')
|
||
|
source = self.eps
|
||
|
ps.write("""
|
||
|
1 1 1 setrgbcolor
|
||
|
newpath
|
||
|
-1 -1 moveto
|
||
|
%(X)d -1 lineto
|
||
|
%(X)d %(Y)d lineto
|
||
|
-1 %(Y)d lineto
|
||
|
closepath
|
||
|
fill
|
||
|
%(mx)d %(my)d translate
|
||
|
0 0 0 setrgbcolor
|
||
|
(%(source)s) run
|
||
|
|
||
|
""" % locals())
|
||
|
|
||
|
sx = int((x2 - x1) * self.scale * self.upscale)
|
||
|
sy = int((y2 - y1) * self.scale * self.upscale)
|
||
|
res = 72 * self.scale * self.upscale
|
||
|
command = ('gs -q -g%dx%d -r%dx%d -sDEVICE=%s -sOutputFile="%s" '
|
||
|
'-dNOPAUSE -dBATCH "%s"') % (
|
||
|
sx, sy, res, res, self.output_format, self.png, ps)
|
||
|
py.process.cmdexec(command)
|
||
|
|
||
|
def scale_image(self):
|
||
|
if self.Image is None:
|
||
|
return
|
||
|
image = self.Image.open(str(self.png))
|
||
|
image.resize((image.size[0] / self.upscale,
|
||
|
image.size[1] / self.upscale),
|
||
|
self.Image.ANTIALIAS).save(str(self.png))
|
||
|
|