#!/usr/bin/env python

"""
tex2png  --  quick latex expression to png conversion tool

Copyright 2008 Ask Hjorth Larsen

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
"""

import sys
import os
from subprocess import Popen, PIPE
from StringIO import StringIO
from optparse import OptionParser

usage = '%prog [options] files'
version = '%prog 0.1'

parser = OptionParser(usage=usage, version=version)
parser.add_option('-r', '--resolution', type='int', metavar='num',
                  default=256,
                  help='output resolution [default: %default]')
parser.add_option('-p', '--preamble', metavar='file',
                  help='include specified file as preamble')
parser.add_option('-v', '--view', action='store_true',
                  help='view image file after generation')
parser.add_option('-T', '--text', action='store_true',
                  help='assume text mode input')
parser.add_option('-N', '--no-clean', action='store_true',
                  help='do not clean up aux/log/dvi files')

opts, args = parser.parse_args()

dvifilename = 'texput.dvi'
logfilename = 'texput.log'
auxfilename = 'texput.aux'
viewcommand = 'qiv'


def tex2png(formula, pngfilename):
    if not formula:
        return
    codebuffer = StringIO()

    def T(text):
        codebuffer.write(text)

    def Tn(text):
        T(text + '\n')

    Tn('\\documentclass{article}')
    for pkg in ['{type1cm}', '[psamsfonts]{amssymb}', '{amsmath}']:
        Tn('\\usepackage%s' % pkg)
    if opts.preamble is not None:
        Tn('\\input{%s}' % opts.preamble)
    Tn('\\begin{document}')
    Tn('\\thispagestyle{empty}')
    if not opts.text:
        Tn('\\begin{eqnarray*}')
    T(formula)
    if not opts.text:
        Tn('\\end{eqnarray*}')
    Tn('\\end{document}')

    code = codebuffer.getvalue()

    latex = Popen('latex', stdout=PIPE, stdin=PIPE)
    latex.stdin.write(code)
    latex.stdin.write('\\end')
    latex.stdin.close()
    exitcode = latex.wait()

    if exitcode != 0:
        print latex.stdout.read()
        return exitcode

    dvipng_args = ['dvipng', 
                   '-q', '-Ttight', '-M', '-pp1', '--noghostscript',
                   '-D%d' % opts.resolution,
                   '-o%s' % pngfilename, 
                   dvifilename]

    dvipng = Popen(dvipng_args, stdin=PIPE, stdout=PIPE)
    dvipng_exitcode = dvipng.wait()
    if dvipng_exitcode != 0:
        print 'Unexpected error (code %d) during dvipng' % dvipng_exitcode
        print dvipng.stdout.read()
    return exitcode


def clean():
    for tempfilename in [dvifilename, logfilename, auxfilename]:
        if os.path.isfile(tempfilename):
            os.remove(tempfilename)


def main():
    pngfilenames = []

    def run(formula, pngfilename):
        exitcode = tex2png(formula, pngfilename)
        if exitcode == 0:
            pngfilenames.append(pngfilename)

    if len(args) == 0:
        formula = sys.stdin.read()
        pngfilename = 'out.png'
        run(formula, pngfilename)

    for filename in args:
        if not filename.endswith('.tex'):
            print 'Warning:', filename, 'is not a .tex file, skipping'
            continue
        formula = open(filename).read()
        pngfilename = filename[:-4] + '.png'
        run(formula, pngfilename)

    if not opts.no_clean:
        clean()
   
    if opts.view and pngfilenames:
        Popen([viewcommand] + pngfilenames)


if __name__ == '__main__':
    main()

