# -*- coding: utf-8 -*-
# Tabellio -- software suite for deliberative assemblies
#          -- suite logicielle pour assemblées délibératives
#          -- http://www.tabellio.org/
# Copyright (C) 2006 Parlement de la Communauté française de Belgique

# This file is part of Tabellio.

# Tabellio 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 2 of the License, or
# (at your option) any later version.

# Tabellio 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, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.

import os,re,string
import logging

from makeutils import mustBuild

log = logging.getLogger("lib.pdfutils")
#_acroread_cmd = _config.get("bin","acroread")
#_gs_cmd = _config.get("bin","gs")

_bbx_val_re = r'[0-9eE\.\-]'
_bbx_re = r'^%%%%BoundingBox:\s+(%s+)\s+(%s+)\s+(%s+)\s+(%s+)\s*$' % \
          ((_bbx_val_re,)*4)
_bbx_re = re.compile(_bbx_re)

def registerTools(path, acroread_cmd="acroread"):
    global _acroread_cmd
    _acroread_cmd      = os.path.join(path, acroread_cmd)

def _fixfn(fn):
    if os.name == "nt":
        fn = fn.replace("\\","/")
    return fn

def gsrun(opts,inFile):
    try:
        gs = os.environ["GS"]
    except KeyError:
        gs = "/usr/bin/gs"
    cmd = gs+" "+opts+" "+inFile
    print cmd
    if os.system(cmd) != 0:
        raise RuntimeError("command '%s' failed" % cmd)

def correctBoundingBox(inf,outf,maxwidth=None):
    while 1:
        l = inf.readline()
        if not l:
            break
        mo = _bbx_re.match(l)
        if mo is not None:
            llx,lly,urx,ury = map(float,mo.groups())
            width = urx - llx
            height = ury - lly
            xoffset = -llx
            yoffset = -lly
            scale = 1.0
            if maxwidth and width > maxwidth:
                scale = maxwidth/width
            outf.write('%%%%BoundingBox: 0 0 %s %s\n' % \
                    (width,height))
            outf.write('/realsetfont /setfont load def\n')
            outf.write('/setfont {\n')
            outf.write('    dup length dict begin\n')
            outf.write('        {1 index /FID ne {def} {pop pop} ifelse} forall\n')
            outf.write('        /Encoding ISOLatin1Encoding def\n')
            outf.write('        currentdict\n')
            outf.write('    end\n')
            outf.write('/Temporary exch definefont\n')
            outf.write('realsetfont\n')
            outf.write('} bind def\n')
            outf.write('<< /PageSize [%s %s] >> setpagedevice\n' % \
                    (width*scale,height*scale))
            outf.write('gsave %s %s translate\n' % \
                    (xoffset,yoffset))
            outf.write('gsave %s %s scale\n' % \
                    (scale,scale))
        else:
            outf.write(string.strip(l)+'\n')

def eps2pdf(infn,outfn=None,maxwidth=5.9*72):
    if not outfn:
        outfn = os.path.splitext(infn)[0]+".pdf"
    if mustBuild(infn,outfn):
        print infn,"->",outfn
        tmpfn = os.path.splitext(infn)[0]+".tmp"
        #tmpfn = "eps2pdf.tmp"
        inf = open(infn)
        tmpf = open(tmpfn,"w")
        try:
            correctBoundingBox(inf,tmpf,maxwidth=maxwidth)
            tmpf.close()
            gsrun("-q -sDEVICE=pdfwrite -sOutputFile=%s " \
                "-dBATCH -dNOPAUSE" % _fixfn(outfn),_fixfn(tmpfn))
        finally:
            tmpf.close()
            os.remove(tmpfn)

def eps2png(infn,outfn=None,maxwidth=4.5*72):
    if not outfn:
        outfn = os.path.splitext(infn)[0]+".png"
    if mustBuild(infn,outfn):
        print infn,"->",outfn
        #tmpfn = os.path.splitext(infn)[0]+".tmp"
        tmpfn = "eps2pdf.tmp"
        inf = open(infn)
        tmpf = open(tmpfn,"w")
        try:
            correctBoundingBox(inf,tmpf,maxwidth=maxwidth)
            tmpf.close()
            gsrun("-q -sDEVICE=png256 -dTextAlphaBits=4 " \
                "-dGraphicsAlphaBits=2 -sOutputFile=%s " \
                "-dBATCH -dNOPAUSE -r144" % _fixfn(outfn),_fixfn(tmpfn))
        finally:
            tmpf.close()
            os.remove(tmpfn)

def pdf2ps(infn,outfn=None):
    global _acroread_cmd
    try:
        if not outfn:
            outfn = os.path.splitext(infn)[0]+".ps"
        if mustBuild(infn,outfn):
            if _acroread_cmd is not None:
                cmd = "%s -toPostScript -pairs %s %s" % (_acroread_cmd,infn,outfn)
                log.info("Convert PDF file: '%s' to PS file '%s' (cmd='%s')" % (infn,outfn,cmd))
                rc = os.system(cmd)
                if rc != 0:
                    raise RuntimeError, "Unable to convert PDF to PS file (cmd='%s')" % cmd
            else:
                cmd = "-sDEVICE=pswrite -sOutputFile=%s -dBATCH -dNOPAUSE " % (outfn)
                log.info("Convert PDF file: '%s' to PS file '%s' (cmd=gs '%s')" % (infn,outfn,cmd))
                gsrun(cmd, infn)
    finally:
        pass

def concatps(infns,outfn):
    outf = None
    try:
        outf = open(outfn,"w")
        log.info("Concat PS files '%s'" % infns)
        for i in range(len(infns)):
            infn = infns[i]
            isLastOne = (i == len(infns) - 1)
            inf = None
            try:
                inf = open(infn,"r")
                if not isLastOne:
                    outf.write("save\n")
                while 1:
                    data = inf.read(4*1024)
                    if len(data) == 0:
                        break
                    outf.write(data)
                if not isLastOne:
                    outf.write("restore\n")
            finally:
                if inf is not None: inf.close()
    finally:
        if outf is not None: outf.close()

def add_content(infn,outfn, before_data=None, after_data=None):
    outf = None
    inf = None
    try:
        outf = open(outfn,"w")
        inf = open(infn,"r")
        if before_data is not None: outf.write(before_data)
        while 1:
            data = inf.read(4*1024)
            if len(data) == 0:
                break
            outf.write(data)
        if after_data is not None: outf.write(after_data)
    finally:
        if inf is not None: inf.close()
        if outf is not None: outf.close()
