# Sketch - A Python-based interactive drawing program
# export_raster script
# Copyright (C) 1999, 2000 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 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 = "-dGraphicsAlphaBits=%d" % 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()

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


def export_raster(context, filename, resolution, use_bbox):
    # parameters:
    #
    # filename: filename of the raster image file
    # gsdevice: ghostscript device name for the raster format, e.g. ppmraw
    # resolution: pixel per inch
    
    # 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)
    finally:
        os.unlink(temp)
    image.save(filename)


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)
