# Sketch - A Python-based interactive drawing program
# Copyright (C) 1998, 1999, 2000, 2002 by Bernhard Herzog
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Library General Public
# License as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later version.
#
# This library 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
# Library General Public License for more details.
#
# You should have received a copy of the GNU Library General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

#
#	A GraphicsObject for Encapsulated Postscript Pictures
#

import os, math

import PIL.Image

from Sketch.Lib import dscparser, util
IsEpsFileStart = dscparser.IsEpsFileStart
from Sketch import _, Point, config

from base import GraphicsObject
from external import ExternalData, get_cached, ExternalGraphics


gs_command = ('gs -sDEVICE=ppmraw -r%(resolution)d -dNOPAUSE -dSAFER -q'
	      ' -sOutputFile=%(temp)s -g%(width)dx%(height)d'
	      ' -c %(offx)f %(offy)f translate'
	      ' /oldshowpage /showpage load def /showpage \'{}\' def '
	      ' -f %(filename)s -c oldshowpage quit')

def render_preview(filename, startx, starty, width, height, resolution = None):
    import tempfile
    temp = tempfile.mktemp()

    try:
        # quote the filename so that it can have spaces and to avoid a
        # security hole
        filename = util.sh_quote(filename)
        if resolution is None:
            resolution = config.preferences.eps_preview_resolution
        factor = resolution / 72.0
        width = int(math.ceil(width * factor))
        height = int(math.ceil(height * factor))
	offx = -startx
	offy = -starty
	os.system(gs_command % locals())

	image = PIL.Image.open(temp)
	image.load()
	return image
    finally:
	try:
	    os.unlink(temp)
	except:
	    pass



class EpsData(ExternalData):

    def __init__(self, filename):
	self.info = info = dscparser.parse_eps_file(filename)
	self.filename = filename
	if info.BoundingBox:
	    llx, lly, urx, ury = info.BoundingBox
	    self.width = Point(urx - llx, 0)
	    self.height = Point(0, ury - lly)
	    self.start = (llx, lly)
	    self.size = (urx - llx, ury - lly)
	    self.image = None
	    try:
		self.image = render_preview(filename, llx, lly,
					    urx - llx, ury - lly)
	    except IOError:
		pass
	else:
	    raise TypeError, '%s has no BoundingBox' % filename

	ExternalData.__init__(self, filename)

    def Start(self):
	return self.start

    def Size(self):
	return self.size

    def WriteLines(self, file):
	write = file.write

	try:
	    infile = open(self.filename, 'r')
	except IOError, val:
	    raise IOError, (filename, val)
	try:
	    readline = infile.readline

	    line = readline()
	    while line:
		if line[:15] == '%%BeginPreview:':
		    while line[:12] != '%%EndPreview':
			line = readline()
		    continue
		write(line)
		line = readline()
	finally:
	    infile.close()


def load_eps(filename):
    eps = get_cached(filename)
    if eps:
	return eps
    return EpsData(filename)


class EpsImage(ExternalGraphics):

    has_edit_mode = 0
    is_Eps = 1

    def __init__(self, filename = '', trafo = None, duplicate = None):
	if duplicate is None:
	    if not filename:
		raise ValueError, 'filename must be provided'
	    data = load_eps(filename)
	else:
	    data = None
	ExternalGraphics.__init__(self, data, trafo,
				  duplicate = duplicate)

    def DrawShape(self, device, rect = None):
	device.DrawEps(self.data, self.trafo)

    def Info(self):
        filename = os.path.basename(self.data.Filename())
        width, height = self.data.Size()
        x, y = self.trafo.offset()
	return _("EpsFile `%(filename)s' %(width)d x %(height)d "
                 "at (%(x)d, %(y)d)") % locals()

    def SaveToFile(self, file):
	file.EpsFile(self.data, self.trafo)

    def PSNeededResources(self):
	return self.data.info.DocumentNeededResources



