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))
 | |
| 
 |