# Sketch - A Python-based interactive drawing program
# export_raster script
# Copyright (C) 1999, 2000, 2002, 2003, 2004 by Bernhard Herzog
# 6.12.2000 improved by Bernhard Reiter with Help form Bernhard
#    (used create_star.py by Tamito KAJIYAMA as an example to
#   build the dialog)
#
# 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

# Export Sketch drawings as raster images using ghostscript to render
# them
#
# This script adds the following to the Script menu:
#
# Export Raster         Renders the drawing on a white background
#
# You can add more with fixed parameters, if you need them frequently
# see the comments below, one example is enabled.
#
# Both commands prompt for a filename. The output file format is
# determined by the filename extension and should be something your PIL
# installation can handle. For the alpha version this should be PNG or
# some other format that can handle an alpha channel.
#

import sys
import os, tempfile

import PIL.Image, PIL.ImageChops

import Sketch.Scripting
from Sketch import _, PostScriptDevice

# for parameter dialogs
from Sketch.UI.sketchdlg import SKModal
from Tkinter import *

class CreateRasterParametersDlg(SKModal):
    "Create Tk Dialog to ask for raster parameters."
    title = _("Choose Raster Parameters")

    def build_dlg(self):
        self.var_ppi = IntVar(self.top)
        self.var_ppi.set(72)
        label = Label(self.top, text=_("ppi"))
        label.grid(column=0, row=0, sticky=E)
        entry = Entry(self.top, width=15, textvariable=self.var_ppi)
        entry.grid(column=1, row=0)

        self.var_alpha = BooleanVar(self.top)
        self.var_alpha.set(1)
        label = Label(self.top, text=_("w. Transparency"))
        label.grid(column=0, row=1, sticky=E)
        entry = Checkbutton(self.top, variable=self.var_alpha)
        entry.grid(column=1, row=1)

        self.var_use_bbox = BooleanVar(self.top)
        self.var_use_bbox.set(0)
        label = Label(self.top, text=_("use BB information"))
        label.grid(column=0, row=2, sticky=E)
        entry = Checkbutton(self.top, variable=self.var_use_bbox)
        entry.grid(column=1, row=2)


        button = Button(self.top, text=_("OK"), command=self.ok)
        button.grid(column=0, row=3, sticky=W)
        button = Button(self.top, text=_("Cancel"), command=self.cancel)
        button.grid(column=1, row=3, sticky=E)

    def ok(self):
        self.close_dlg((self.var_ppi.get(),
                        self.var_alpha.get(),self.var_use_bbox.get()))

def export_raster_more_interactive(context, alpha = 0, use_bbox = 0,
                                   render_ppi=72):
    "Get Parameter per dialog and run export_raster_interactive()"
    parms = CreateRasterParametersDlg(context.application.root).RunDialog()
    if parms is None:
        return
    else:
        render_ppi=parms[0]
        alpha=parms[1]
        use_bbox=parms[2]

        return export_raster_interactive(context,alpha,use_bbox,render_ppi)


def make_ps(document):
    file = tempfile.mktemp('.ps')
    device = PostScriptDevice(file, as_eps = 0, document = document)
    document.Draw(device)
    device.Close()
    return file


def render_ps(filename, resolution, width, height, orig_x = 0, orig_y = 0,
              prolog = '', antialias = '', gsdevice = 'ppmraw'):
    if prolog:
        prolog = '-c ' + '"' + prolog + '"'

    if antialias:
        antialias = ("-dTextAlphaBits=%d -dGraphicsAlphaBits=%d"
                     % (antialias, antialias))
    else:
        antialias = ""

    orig_x = -orig_x
    orig_y = -orig_y

    temp = tempfile.mktemp()

    try:
        gs_cmd = ('gs -dNOPAUSE -g%(width)dx%(height)d -r%(resolution)d '
                  '-sOutputFile=%(temp)s %(antialias)s '
                  '-sDEVICE=%(gsdevice)s -q %(prolog)s '
                  '-c %(orig_x)f %(orig_y)f translate '
                  '-f%(filename)s -c quit')
        gs_cmd = gs_cmd % locals()
        retval = os.system(gs_cmd)
        if retval:
            sys.stderr.write("skencil:export_raster: executing %s failed"
                             " with exit code %x\n" % (repr(gs_cmd), retval))
            raise IOError("Error running ghostscript."
                          "  Perhaps it's not installed.")
        image = PIL.Image.open(temp)
        image.load()
        return image
    finally:
       try:
           os.unlink(temp)
       except:
           pass


def export_raster(context, filename, resolution, use_bbox, format = None,
                  antialias = None):
    # instead of the page size one could also use the bounding box
    # (returned by the BoundingRect method).
    if use_bbox:
        left, bottom, right, top = context.document.BoundingRect()
        width = right - left
        height = top - bottom
        x = left; y = bottom
    else:
        width, height = context.document.PageSize()
        x = y = 0
    width = round(width * resolution / 72.0)
    height = round(height * resolution / 72.0)

    temp = make_ps(context.document)
    try:
        image = render_ps(temp, resolution, width, height,
                          orig_x = x, orig_y = y, antialias = antialias)
    finally:
        os.unlink(temp)
    image.save(filename, format = format)


alpha_prolog = "/setrgbcolor {pop pop pop 0 0 0 setrgbcolor} bind def \
/setgray { pop 0 setgray} bind def \
/setcmykcolor { pop pop pop pop 0 0 0 1.0 setcmykcolor} bind def "

def export_alpha(context, filename, resolution, use_bbox = 0):
    if use_bbox:
        left, bottom, right, top = context.document.BoundingRect()
        width = right - left
        height = top - bottom
        x = left; y = bottom
    else:
        width, height = context.document.PageSize()
        x = y = 0

    ps = make_ps(context.document)

    width = round(width * resolution / 72.0)
    height = round(height * resolution / 72.0)
    rgb = render_ps(ps, resolution, width, height,
                    orig_x = x, orig_y = y, antialias = 2)
    alpha = render_ps(ps, resolution, width, height,
                      orig_x = x, orig_y = y, antialias = 2,
                      prolog = alpha_prolog, gsdevice = 'pgmraw')

    alpha = PIL.ImageChops.invert(alpha)

    rgb = rgb.convert('RGBA')
    rgb.putalpha(alpha)
    rgb.save(filename)



filelist = [(_("Portable Pixmap"), '.ppm'),
            (_("Portable Graymap"), '.pgm'),
            (_("Jpeg"),   '.jpg'),
            (_("Portable Network Graphics"), '.png')]

def export_raster_interactive(context, alpha = 0, use_bbox = 0, render_ppi=72):
    # popup a filedialog and export the document

    doc = context.document

    # construct the tk filetypes list
    extensions = {}
    for text, ext in filelist:
        extensions[ext] = 1

    # determine a default filename
    basename = os.path.splitext(doc.meta.filename)[0]
    if alpha:
        default_ext = '.png'
        # shift png up in filetypes so it is displayed accordingly
        filetypes=tuple(filelist[-1:]+filelist[1:-1])
    else:
        default_ext = '.ppm'
        filetypes=tuple(filelist)

    filename = context.application.GetSaveFilename(
        title = _("Export Raster"),
        filetypes = filetypes,
        initialdir = doc.meta.directory,
        initialfile = basename + default_ext)
    if filename:
        ext = os.path.splitext(filename)[1]
        if extensions.has_key(ext):
            if alpha:
                export_alpha(context, filename, render_ppi, use_bbox)
            else:
                export_raster(context, filename, render_ppi, use_bbox)
        else:
            message = _("unknown extension %s") % ext
            context.application.MessageBox(title = _("Export Raster"),
                                           message = message)




Sketch.Scripting.AddFunction('export_raster', _("Export Raster"),
                             export_raster_more_interactive,
                             script_type = Sketch.Scripting.AdvancedScript)
#Sketch.Scripting.AddFunction('export_raster', 'Export Raster Alpha (Default)',
#                             export_raster_interactive, args = (1,0),
#                             script_type = Sketch.Scripting.AdvancedScript)
Sketch.Scripting.AddFunction('export_raster',
                             _("Export Raster Alpha (100ppi)"),
                             export_raster_interactive, args = (1,0,100),
                             script_type = Sketch.Scripting.AdvancedScript)
#Sketch.Scripting.AddFunction('export_raster', 'Export Raster Alpha (120ppi)',
#                             export_raster_interactive, args = (1,0,120),
#                             script_type = Sketch.Scripting.AdvancedScript)
