🚨 Latest Research:Tanstack npm Packages Compromised in Ongoing Mini Shai-Hulud Supply-Chain Attack.Learn More
Socket
Book a DemoSign in
Socket

ghostscript

Package Overview
Dependencies
Maintainers
1
Versions
10
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

ghostscript - pypi Package Compare versions

Comparing version
0.6
to
0.5.dev0
+1
./usr/lib/python3....ev0-py3.5.egg-info/dependency_links.txt
Metadata-Version: 1.1
Name: ghostscript
Version: 0.5.dev0
Summary: Interface to the Ghostscript C-API, both high- and low-level, based on ctypes
Home-page: https://gitlab.com/pdftools/python-ghostscript
Author: Hartmut Goebel
Author-email: h.goebel@crazy-compilers.com
License: GPL 3.0
Download-URL: http://pypi.python.org/pypi/ghostscript
Description-Content-Type: UNKNOWN
Description: ==========================
`python-ghostscript`
==========================
---------------------------------------------------------------------
Python-Interface to the Ghostscript C-API
---------------------------------------------------------------------
:Author: Hartmut Goebel <h.goebel@crazy-compiler.com>
:Version: 0.5dev
:Copyright: GNU Public License v3 (GPLv3)
:Homepage: https://gitlab.com/pdftools/python-ghostscript
`Ghostscript`__ is a well known interpreter for the PostScript
language and for PDF. This package implements a interface to the
`Ghostscript C-API`__ using `ctypes`__. Both a low-level and a pythonic,
high-level interface are provided.
__ http://www.ghostscript.com/
__ http://pages.cs.wisc.edu/~ghost/doc/cvs/API.htm
__ http://docs.python.org/library/ctypes.html
This package is currently tested only under GNU/Linux. Please report
whether it works in your environment, too. Thanks.
Example
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Here is an example for how to use the high-level interface of
`python-ghostscript`. This implements a very basic ps2pdf-tool::
import sys
import locale
import ghostscript
args = [
"ps2pdf", # actual value doesn't matter
"-dNOPAUSE", "-dBATCH", "-dSAFER",
"-sDEVICE=pdfwrite",
"-sOutputFile=" + sys.argv[1],
"-c", ".setpdfwrite",
"-f", sys.argv[2]
]
# arguments have to be bytes, encode them
encoding = locale.getpreferredencoding()
args = [a.encode(encoding) for a in args]
ghostscript.Ghostscript(*args)
Here an example for passing a string document to Ghostscript::
doc = b"""%!
/Helvetica findfont 20 scalefont setfont
50 50 moveto
(Hello World) show
showpage
quit
"""
import ghostscript
args = b"""test.py
-dNOPAUSE -dBATCH -dSAFER -sDEVICE=pdfwrite -sOutputFile=/tmp/out.pdf
-c .setpdfwrite""".split()
with ghostscript.Ghostscript(*args) as gs:
gs.run_string(doc)
More examples can be found in the `examples` subdirectory of the
distribution archive.
Requirements and Installation
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
:Please note: This package is meant for developers. Even if there are
some usable examples included, installations instructions are meant
for developers.
`python-ghostscript` requires
* `Python`__ 2.7 or higher (tested with Python 2.7 and 3.4)
* `setuptools`__ for installation (see below)
* `Ghostscript`__ Version 8.x or higher
__ http://www.python.org/download/
__ http://pypi.python.org/pypi/setuptools
__ http://www.ghostscript.com/
Installing python-ghostscript
---------------------------------
Since this package is meant for developers, we assume you have
experience in installing Python packages.
`python-ghostscript` is listed on `PyPI (Python Package Index)`__, so
you can install it using `pip install ghostscript` as usual. Please
refer to the manuals of `pip` for further information.
__ http://pypi.python.org/pypi
Alternatively you my download and unpack the source package of
`python-ghostscript` from http://pypi.python.org/pypi/ghostscript and
run::
python ./setup.py install
.. Emacs config:
Local Variables:
mode: rst
ispell-local-dictionary: "american"
End:
Keywords: Ghostscript,PDF,Postscript
Platform: UNKNOWN
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: GNU General Public License (GPL)
Classifier: Natural Language :: English
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 2.7
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Software Development :: Libraries :: Python Modules
CHANGES.txt
COPYING
MANIFEST.in
README.rst
SConstruct
projectlogo.svg
setup.cfg
setup.py
examples/gs.py
examples/lowlevel1.py
examples/lowlevel2.py
examples/lowlevel3.py
examples/ps2pdf.py
examples/run-string.bat
examples/run-string.py
examples/test-gs.sh
examples/test-lowlevel2.sh
examples/test-lowlevel3.sh
examples/test-ps2pdf.sh
examples/test.ps
ghostscript/__init__.py
ghostscript/_errors.py
ghostscript/_gsprint.py
ghostscript.egg-info/PKG-INFO
ghostscript.egg-info/SOURCES.txt
ghostscript.egg-info/dependency_links.txt
ghostscript.egg-info/requires.txt
ghostscript.egg-info/top_level.txt
ghostscript.egg-info/zip-safe
test/test_highlevel.py
test/test_lowlevel.py

Sorry, the diff of this file is not supported yet

#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
ghostscript - A Python interface for the Ghostscript interpreter C-API
"""
#
# Copyright 2010-2016 by Hartmut Goebel <h.goebel@crazy-compilers.com>
#
# 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/>.
#
from __future__ import absolute_import
__author__ = "Hartmut Goebel <h.goebel@crazy-compilers.com>"
__copyright__ = "Copyright 2010-2016 by Hartmut Goebel <h.goebel@crazy-compilers.com>"
__licence__ = "GNU General Public License version 3 (GPL v3)"
__version__ = "0.5dev"
__all__ = ['Ghostscript', 'revision',
'GhostscriptError', 'PleaseDisplayUsage']
import atexit
import sys # :todo: remove, debugging only
from . import _gsprint as gs
GhostscriptError = gs.GhostscriptError
def PleaseDisplayUsage(Warning):
"""
This exception is raised when Ghostscript asks the application to
display the usage. The application should catch the exception an
print the usage message.
"""
pass
def revision():
"""
This function returns the revision numbers and strings of the
Ghostscript interpreter library as a dict. You should call it
before any other interpreter library functions to make sure that
the correct version of the Ghostscript interpreter has been
loaded.
"""
rev = gs.revision()
return dict((f, getattr(rev, f)) for f, _ in rev._fields_)
MAX_STRING_LENGTH = gs.MAX_STRING_LENGTH
class Ghostscript(object):
@staticmethod
def revision():
return revision()
def __init__(self, instance, args, stdin=None, stdout=None, stderr=None):
self._initialized = False
self._instance = instance
self._callbacks = None
if stdin or stdout or stderr:
self.set_stdio(stdin, stdout, stderr)
rc = gs.init_with_args(instance, args)
if rc == gs.e_Info:
raise PleaseDisplayUsage
self._initialized = True
if rc == gs.e_Quit:
self.exit()
def __enter__(self):
return self
def __exit__(self, *args):
self.exit()
def set_stdio(self, stdin=None, stdout=None, stderr=None):
"""Set stdin, stdout and stderr of the ghostscript interpreter.
The ``stdin`` stream has to support the ``readline()``
interface. The ``stdout`` and ``stderr`` streams have to
support the ``write()`` and ``flush()`` interface.
Please note that this does not affect the input- and output-
streams of the devices. Esp. setting stdout does not allow
catching the devise-output even when using ``-sOutputFile=-``.
"""
self._callbacks = (
stdin and gs._wrap_stdin(stdin) or None,
stdout and gs._wrap_stdout(stdout) or None,
stderr and gs._wrap_stderr(stderr) or None,
)
gs.set_stdio(self._instance, *self._callbacks)
def __del__(self):
self.exit()
def exit(self):
global __instance__
if self._initialized:
if __instance__:
#gs.exit(self._instance)
self._instance = None
self._initialized = False
def run_string(self, str, user_errors=False):
"""
Run the string ``str`` by Ghostscript
This takes care of Ghostscripts size-limitations and passes
the string in pieces if necessary.
"""
instance = self._instance
if len(str) < MAX_STRING_LENGTH:
gs.run_string(instance, str)
else:
gs.run_string_begin(instance)
for start in range(0, len(str), MAX_STRING_LENGTH):
gs.run_string_continue(instance,
str[start:start+MAX_STRING_LENGTH])
gs.run_string_end(instance)
def run_filename(self, filename, user_errors=False):
"""
Run the file named by ``filename`` by Ghostscript
"""
return gs.run_file(self._instance, filename, user_errors)
def run_file(self, file, user_errors=False):
"""
Read ``file`` and run the content by Ghostscript.
``file`` must already by opened and may by any file-like
object supporting the ``read()`` method.
"""
instance = self._instance
gs.run_string_begin(instance)
while True:
str = file.read(MAX_STRING_LENGTH)
if not str:
break
gs.run_string_continue(instance, str)
gs.run_string_end(instance)
__Ghostscript = Ghostscript
__instance__ = None
def Ghostscript(*args, **kw):
"""
Factory function for setting up a Ghostscript instance
"""
global __instance__, __object_count__
# Ghostscript only supports a single instance
if __instance__ is None:
__instance__ = gs.new_instance()
return __Ghostscript(__instance__, args,
stdin=kw.get('stdin', None),
stdout=kw.get('stdout', None),
stderr=kw.get('stderr', None))
def cleanup():
global __instance__
if __instance__ is not None:
gs.delete_instance(__instance__)
__instance__ = None
#atexit.register(cleanup)

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

"""
Definition of Ghostscript error codes
"""
#
# Copyright (C) 2010-2016 by Hartmut Goebel
#
# Based on iapi.h which is
# Copyright (C) 1989, 1995, 1998, 1999 Aladdin Enterprises. All rights reserved.
#
# 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/>.
#
__author__ = "Hartmut Goebel <h.goebel@crazy-compilers.com>"
__copyright__ = "Copyright 2010-2016 by Hartmut Goebel <h.goebel@crazy-compilers.com>"
__licence__ = "GNU General Public License version 3 (GPL v3)"
#
# A procedure that may return an error always returns
# a non-negative value (zero, unless otherwise noted) for success,
# or negative for failure.
# We use ints rather than an enum to avoid a lot of casting.
#
# ------ PostScript Level 1 errors ------
e_unknownerror = -1 # unknown error
e_dictfull = -2
e_dictstackoverflow = -3
e_dictstackunderflow = -4
e_execstackoverflow = -5
e_interrupt = -6
# We also need to define gs_error_interrupt, for gpcheck.h
gs_error_interrupt = e_interrupt
e_invalidaccess = -7
e_invalidexit = -8
e_invalidfileaccess = -9
e_invalidfont = -10
e_invalidrestore = -11
e_ioerror = -12
e_limitcheck = -13
e_nocurrentpoint = -14
e_rangecheck = -15
e_stackoverflow = -16
e_stackunderflow = -17
e_syntaxerror = -18
e_timeout = -19
e_typecheck = -20
e_undefined = -21
e_undefinedfilename = -22
e_undefinedresult = -23
e_unmatchedmark = -24
e_VMerror = -25
LEVEL1_ERROR_NAMES = ["unknownerror", "dictfull", "dictstackoverflow",
"dictstackunderflow", "execstackoverflow",
"interrupt", "invalidaccess", "invalidexit",
"invalidfileaccess", "invalidfont",
"invalidrestore", "ioerror", "limitcheck",
"nocurrentpoint", "rangecheck", "stackoverflow",
"stackunderflow", "syntaxerror", "timeout",
"typecheck", "undefined", "undefinedfilename",
"undefinedresult", "unmatchedmark", "VMerror"]
# ------ Additional Level 2 and DPS errors ------
e_configurationerror = -26
e_invalidcontext = -27
e_undefinedresource = -28
e_unregistered = -29
# invalidid is for the NeXT DPS extension.
e_invalidid = -30
LEVEL2_ERROR_NAMES = ["configurationerror", "invalidcontext",
"undefinedresource", "unregistered",
"invalidid"]
ERROR_NAMES = LEVEL1_ERROR_NAMES + LEVEL2_ERROR_NAMES
_PSEUDO_ERRORS = ['Fatal', 'Quit', 'InterpreterExit', 'RemapColor',
'ExecStackUnderflow', 'VMreclaim', 'NeedInput',
'NeedStdin', 'NeedStdout', 'NeedStderr', 'Info']
def error2name(ecode):
if ecode <= e_Fatal:
return _PSEUDO_ERRORS[-ecode-100]
else:
return ERROR_NAMES[-ecode-1]
# ------ Pseudo-errors used internally ------
#
# Internal code for a fatal error.
# gs_interpret also returns this for a .quit with a positive exit code.
#
e_Fatal = -100
#
# Internal code for the .quit operator.
# The real quit code is an integer on the operand stack.
# gs_interpret returns this only for a .quit with a zero exit code.
#
e_Quit = -101
#
# Internal code for a normal exit from the interpreter.
# Do not use outside of interp.c.
#
e_InterpreterExit = -102
#
# Internal code that indicates that a procedure has been stored in the
# remap_proc of the graphics state, and should be called before retrying
# the current token. This is used for color remapping involving a call
# back into the interpreter -- inelegant, but effective.
#
e_RemapColor = -103
#
# Internal code to indicate we have underflowed the top block
# of the e-stack.
#
e_ExecStackUnderflow = -104
#
# Internal code for the vmreclaim operator with a positive operand.
# We need to handle this as an error because otherwise the interpreter
# won't reload enough of its state when the operator returns.
#
e_VMreclaim = -105
#
# Internal code for requesting more input from run_string.
#
e_NeedInput = -106
#
# Internal code for stdin callout.
#
e_NeedStdin = -107
#
# Internal code for stdout callout.
#
e_NeedStdout = -108
#
# Internal code for stderr callout.
#
e_NeedStderr = -109
#
# Internal code for a normal exit when usage info is displayed.
# This allows Window versions of Ghostscript to pause until
# the message can be read.
#
e_Info = -110
#
# Define which error codes require re-executing the current object.
#
def ERROR_IS_INTERRUPT(ecode):
return ecode == e_interrupt or ecode == e_timeout
if __name__ == '__main__':
print(error2name(e_unknownerror) == "unknownerror")
print(error2name(e_VMerror) == "VMerror")
print(error2name(e_invalidid) == "invalidid")
print(error2name(e_VMreclaim) == "VMreclaim")
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
ghostscript._gsprint - A low-lewel interface to the Ghostscript C-API using ctypes
"""
#
# Copyright 2010-2016 by Hartmut Goebel <h.goebel@crazy-compilers.com>
#
# Display_callback Structure by Lasse Fister <commander@graphicore.de> in 2013
#
# 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/>.
#
from __future__ import absolute_import
__author__ = "Hartmut Goebel <h.goebel@crazy-compilers.com>"
__copyright__ = "Copyright 2010-2016 by Hartmut Goebel <h.goebel@crazy-compilers.com>"
__licence__ = "GNU General Public License version 3 (GPL v3)"
__version__ = "0.5dev"
from ctypes import *
import sys
from ._errors import *
MAX_STRING_LENGTH = 65535
DISPLAY_VERSION_MAJOR = 2
DISPLAY_VERSION_MINOR = 0
DISPLAY_VERSION_MAJOR_V1 = 1 # before separation format was added
DISPLAY_VERSION_MINOR_V1 = 0
# The display format is set by a combination of the following bitfields
# Define the color space alternatives
# DISPLAY_FORMAT_COLOR
DISPLAY_COLORS_NATIVE = (1<<0)
DISPLAY_COLORS_GRAY = (1<<1)
DISPLAY_COLORS_RGB = (1<<2)
DISPLAY_COLORS_CMYK = (1<<3)
DISPLAY_COLORS_SEPARATION = (1<<19)
DISPLAY_COLORS_MASK = 0x8000f
# Define whether alpha information, or an extra unused bytes is included
# DISPLAY_ALPHA_FIRST and DISPLAY_ALPHA_LAST are not implemented
# DISPLAY_FORMAT_ALPHA
DISPLAY_ALPHA_NONE = (0<<4)
DISPLAY_ALPHA_FIRST = (1<<4)
DISPLAY_ALPHA_LAST = (1<<5)
DISPLAY_UNUSED_FIRST = (1<<6) # e.g. Mac xRGB
DISPLAY_UNUSED_LAST = (1<<7) # e.g. Windows BGRx
DISPLAY_ALPHA_MASK = 0x00f0
# Define the depth per component for DISPLAY_COLORS_GRAY,
# DISPLAY_COLORS_RGB and DISPLAY_COLORS_CMYK,
# or the depth per pixel for DISPLAY_COLORS_NATIVE
# DISPLAY_DEPTH_2 and DISPLAY_DEPTH_12 have not been tested.
# DISPLAY_FORMAT_DEPTH
DISPLAY_DEPTH_1 = (1<< 8)
DISPLAY_DEPTH_2 = (1<< 9)
DISPLAY_DEPTH_4 = (1<<10)
DISPLAY_DEPTH_8 = (1<<11)
DISPLAY_DEPTH_12 = (1<<12)
DISPLAY_DEPTH_16 = (1<<13)
# unused (1<<14)
# unused (1<<15)
DISPLAY_DEPTH_MASK = 0xff00
# Define whether Red/Cyan should come first,
# or whether Blue/Black should come first
# DISPLAY_FORMAT_ENDIAN
DISPLAY_BIGENDIAN = (0<<16) # Red/Cyan first
DISPLAY_LITTLEENDIAN = (1<<16) # Blue/Black first
DISPLAY_ENDIAN_MASK = 0x00010000
# Define whether the raster starts at the top or bottom of the bitmap
# DISPLAY_FORMAT_FIRSTROW
DISPLAY_TOPFIRST = (0<<17) # Unix, Mac
DISPLAY_BOTTOMFIRST = (1<<17) # Windows
DISPLAY_FIRSTROW_MASK = 0x00020000
# Define whether packing RGB in 16-bits should use 555
# or 565 (extra bit for green)
# DISPLAY_FORMAT_555
DISPLAY_NATIVE_555 = (0<<18)
DISPLAY_NATIVE_565 = (1<<18)
DISPLAY_555_MASK = 0x00040000
# Define the row alignment, which must be equal to or greater than
# the size of a pointer.
# The default (DISPLAY_ROW_ALIGN_DEFAULT) is the size of a pointer,
# 4 bytes (DISPLAY_ROW_ALIGN_4) on 32-bit systems or 8 bytes
# (DISPLAY_ROW_ALIGN_8) on 64-bit systems.
# DISPLAY_FORMAT_ROW_ALIGN
DISPLAY_ROW_ALIGN_DEFAULT = (0<<20)
# DISPLAY_ROW_ALIGN_1 = (1<<20), # not currently possible
# DISPLAY_ROW_ALIGN_2 = (2<<20), # not currently possible
DISPLAY_ROW_ALIGN_4 = (3<<20)
DISPLAY_ROW_ALIGN_8 = (4<<20)
DISPLAY_ROW_ALIGN_16 = (5<<20)
DISPLAY_ROW_ALIGN_32 = (6<<20)
DISPLAY_ROW_ALIGN_64 = (7<<20)
DISPLAY_ROW_ALIGN_MASK = 0x00700000
class Revision(Structure):
_fields_ = [
("product", c_char_p),
("copyright", c_char_p),
("revision", c_long),
("revisiondate", c_long)
]
gs_main_instance = c_void_p
display_callback = c_void_p
class GhostscriptError(Exception):
def __init__(self, ecode):
# :todo:
Exception.__init__(self, error2name(ecode))
self.code = ecode
def revision():
"""
Get version numbers and strings.
This is safe to call at any time.
You should call this first to make sure that the correct version
of the Ghostscript is being used.
Returns a Revision instance
"""
revision = Revision()
rc = libgs.gsapi_revision(pointer(revision), sizeof(revision))
if rc:
raise ArgumentError("Revision structure size is incorrect, "
"requires %s bytes" % rc)
return revision
def new_instance(): # display_callback=None):
"""
Create a new instance of Ghostscript
This instance is passed to most other API functions.
"""
# :todo: The caller_handle will be provided to callback functions.
display_callback=None
instance = gs_main_instance()
rc = libgs.gsapi_new_instance(pointer(instance), display_callback)
if rc != 0:
raise GhostscriptError(rc)
return instance
def delete_instance(instance):
"""
Destroy an instance of Ghostscript
Before you call this, Ghostscript must have finished.
If Ghostscript has been initialised, you must call exit()
before delete_instance()
"""
return libgs.gsapi_delete_instance(instance)
c_stdstream_call_t = CFUNCTYPE(c_int, gs_main_instance, POINTER(c_char), c_int)
def _wrap_stdin(infp):
"""
Wrap a filehandle into a C function to be used as `stdin` callback
for ``set_stdio``. The filehandle has to support the readline() method.
"""
def _wrap(instance, dest, count):
try:
data = infp.readline(count)
except:
count = -1
else:
if not data:
count = 0
else:
count = len(data)
memmove(dest, c_char_p(data), count)
return count
return c_stdstream_call_t(_wrap)
def _wrap_stdout(outfp):
"""
Wrap a filehandle into a C function to be used as `stdout` or
`stderr` callback for ``set_stdio``. The filehandle has to support the
write() and flush() methods.
"""
def _wrap(instance, str, count):
outfp.write(str[:count])
outfp.flush()
return count
return c_stdstream_call_t(_wrap)
_wrap_stderr = _wrap_stdout
def set_stdio(instance, stdin, stdout, stderr):
"""
Set the callback functions for stdio.
``stdin``, ``stdout`` and ``stderr`` have to be ``ctypes``
callback functions matching the ``_gsprint.c_stdstream_call_t``
prototype. You may want to use _wrap_* to wrap file handles.
Note 1: This function only changes stdio of the Postscript
interpreter, not that of the devices.
Note 2: Make sure you keep references to C function objects
as long as they are used from C code. Otherwise they may be
garbage collected, crashing your program when a callback is made.
The ``stdin`` callback function should return the number of
characters read, `0` for EOF, or `-1` for error. The `stdout` and
`stderr` callback functions should return the number of characters
written.
You may pass ``None`` for any of stdin, stdout or stderr , in which
case the system stdin, stdout resp. stderr will be used.
"""
rc = libgs.gsapi_set_stdio(instance, stdin, stdout, stderr)
if rc not in (0, e_Quit, e_Info):
raise GhostscriptError(rc)
return rc
# :todo: set_poll (instance, int(*poll_fn)(void *caller_handle));
# :todo: set_display_callback(instance, callback):
def init_with_args(instance, argv):
"""
Initialise the interpreter.
1. If quit or EOF occur during init_with_args(), the return value
will be e_Quit. This is not an error. You must call exit() and
must not call any other functions.
2. If usage info should be displayed, the return value will be
e_Info which is not an error. Do not call exit().
3. Under normal conditions this returns 0. You would then call one
or more run_*() functions and then finish with exit()
"""
ArgArray = c_char_p * len(argv)
c_argv = ArgArray(*argv)
rc = libgs.gsapi_init_with_args(instance, len(argv), c_argv)
if rc not in (0, e_Quit, e_Info):
raise GhostscriptError(rc)
return rc
def exit(instance):
"""
Exit the interpreter
This must be called on shutdown if init_with_args() has been
called, and just before delete_instance()
"""
rc = libgs.gsapi_exit(instance)
if rc != 0:
raise GhostscriptError(rc)
return rc
def run_string_begin(instance, user_errors=False):
exit_code = c_int()
rc = libgs.gsapi_run_string_begin(instance, c_int(user_errors),
pointer(exit_code))
if rc != 0:
raise GhostscriptError(rc)
return exit_code.value
def run_string_continue(instance, str, user_errors=False):
exit_code = c_int()
rc = libgs.gsapi_run_string_continue(
instance, c_char_p(str), c_int(len(str)),
c_int(user_errors), pointer(exit_code))
if rc != e_NeedInput and rc != 0:
raise GhostscriptError(rc)
return exit_code.value
def run_string_end(instance, user_errors=False):
exit_code = c_int()
rc = libgs.gsapi_run_string_end(instance, c_int(user_errors),
pointer(exit_code))
if rc != 0:
raise GhostscriptError(rc)
return exit_code.value
def run_string_with_length(*args, **kw):
raise NotImpelmentedError('Use run_string() instead')
def run_string(instance, str, user_errors=False):
exit_code = c_int()
rc = libgs.gsapi_run_string_with_length(
instance, c_char_p(str), c_int(len(str)),
c_int(user_errors), pointer(exit_code))
if rc != 0:
raise GhostscriptError(rc)
return exit_code.value
def run_file(instance, filename, user_errors=False):
exit_code = c_int()
rc = libgs.gsapi_run_file(instance, c_char_p(filename),
c_int(user_errors), pointer(exit_code))
if rc != 0:
raise GhostscriptError(rc)
return exit_code.value
def set_visual_tracer(I):
raise NotImplementedError
# New device has been opened
# This is the first event from this device.
# int (*display_open)(void *handle, void *device);
c_display_open = CFUNCTYPE(c_int, c_void_p, c_void_p)
# Device is about to be closed.
# Device will not be closed until this function returns.
#int (*display_preclose)(void *handle, void *device);
c_display_preclose = CFUNCTYPE(c_int, c_void_p, c_void_p)
# Device has been closed.
# This is the last event from this device.
# int (*display_close)(void *handle, void *device);
c_display_close = CFUNCTYPE(c_int, c_void_p, c_void_p)
# Device is about to be resized.
# Resize will only occur if this function returns 0.
# raster is byte count of a row.
# int (*display_presize)(void *handle, void *device,
# int width, int height, int raster, unsigned int format);
c_display_presize = CFUNCTYPE(c_int, c_void_p, c_void_p,
c_int, c_int, c_int, c_uint)
# Device has been resized.
# New pointer to raster returned in pimage
# int (*display_size)(void *handle, void *device, int width, int height,
# int raster, unsigned int format, unsigned char *pimage);
c_display_size = CFUNCTYPE(c_int, c_void_p, c_void_p,
c_int, c_int, c_int, c_uint, POINTER(c_ubyte))
# flushpage
#int (*display_sync)(void *handle, void *device);
c_display_sync = CFUNCTYPE(c_int, c_void_p, c_void_p)
# showpage
# If you want to pause on showpage, then don't return immediately
# int (*display_page)(void *handle, void *device, int copies, int flush);
c_display_page = CFUNCTYPE(c_int, c_void_p, c_void_p,
c_int, c_int)
# Notify the caller whenever a portion of the raster is updated.
# This can be used for cooperative multitasking or for
# progressive update of the display.
# This function pointer may be set to NULL if not required.
# int (*display_update)(void *handle, void *device, int x, int y,
# int w, int h);
c_display_update = CFUNCTYPE(c_int, c_void_p, c_void_p,
c_int, c_int, c_int, c_int)
# Allocate memory for bitmap
# This is provided in case you need to create memory in a special
# way, e.g. shared. If this is NULL, the Ghostscript memory device
# allocates the bitmap. This will only called to allocate the
# image buffer. The first row will be placed at the address
# returned by display_memalloc.
# void *(*display_memalloc)(void *handle, void *device, unsigned long size);
c_display_memalloc = CFUNCTYPE(c_void_p, c_void_p, c_void_p, c_ulong)
# Free memory for bitmap
# If this is NULL, the Ghostscript memory device will free the bitmap
# int (*display_memfree)(void *handle, void *device, void *mem);
c_display_memfree = CFUNCTYPE(c_int, c_void_p, c_void_p, c_void_p)
# Added in V2 */
# When using separation color space (DISPLAY_COLORS_SEPARATION),
# give a mapping for one separation component.
# This is called for each new component found.
# It may be called multiple times for each component.
# It may be called at any time between display_size
# and display_close.
# The client uses this to map from the separations to CMYK
# and hence to RGB for display.
# GS must only use this callback if version_major >= 2.
# The unsigned short c,m,y,k values are 65535 = 1.0.
# This function pointer may be set to NULL if not required.
#
# int (*display_separation)(void *handle, void *device,
# int component, const char *component_name,
# unsigned short c, unsigned short m,
# unsigned short y, unsigned short k);
c_display_separation = CFUNCTYPE(c_int, c_void_p, c_void_p,
c_int, c_char_p, c_ushort, c_ushort, c_ushort, c_ushort)
class Display_callback_s (Structure):
_fields_ = [
# Size of this structure
# Used for checking if we have been handed a valid structure
# int size;
("size", c_int),
# Major version of this structure
# The major version number will change if this structure changes.
# int version_major;
("version_major", c_int),
# Minor version of this structure
# The minor version number will change if new features are added
# without changes to this structure. For example, a new color
# format.
#int version_minor;
("version_minor", c_int),
("display_open", c_display_open),
("display_preclose", c_display_preclose),
("display_close", c_display_close),
("display_presize", c_display_presize),
("display_size", c_display_size),
("display_sync", c_display_sync),
("display_page", c_display_page),
("display_update", c_display_update),
("display_memalloc", c_display_memalloc),
("display_memfree", c_display_memfree),
("display_separation", c_display_separation)
]
def set_display_callback(instance, callback):
rc = libgs.gsapi_set_display_callback(instance, callback)
if rc != 0:
raise GhostscriptError(rc)
return rc
def __win32_finddll():
try:
import winreg
except ImportError:
# assume Python 2
from _winreg import OpenKey, CloseKey, EnumKey, QueryValueEx, \
QueryInfoKey, HKEY_LOCAL_MACHINE
else:
from winreg import OpenKey, CloseKey, EnumKey, QueryValueEx, \
QueryInfoKey, HKEY_LOCAL_MACHINE
from distutils.version import LooseVersion
import os
dlls = []
# Look up different variants of Ghostscript and take the highest
# version for which the DLL is to be found in the filesystem.
for key_name in ('AFPL Ghostscript', 'Aladdin Ghostscript',
'GPL Ghostscript', 'GNU Ghostscript'):
try:
k1 = OpenKey(HKEY_LOCAL_MACHINE, "Software\\%s" % key_name)
for num in range(0, QueryInfoKey(k1)[0]):
version = EnumKey(k1, num)
try:
k2 = OpenKey(k1, version)
dll_path = QueryValueEx(k2, 'GS_DLL')[0]
CloseKey(k2)
if os.path.exists(dll_path):
dlls.append((LooseVersion(version), dll_path))
except WindowsError:
pass
CloseKey(k1)
except WindowsError:
pass
if dlls:
dlls.sort()
return dlls[-1][-1]
else:
return None
if sys.platform == 'win32':
libgs = __win32_finddll()
if not libgs:
raise RuntimeError('Can not find Ghostscript DLL in registry')
libgs = windll.LoadLibrary(libgs)
else:
try:
libgs = cdll.LoadLibrary("libgs.so")
except OSError:
# shared object file not found
import ctypes.util
libgs = ctypes.util.find_library('gs')
if not libgs:
raise RuntimeError('Can not find Ghostscript library (libgs)')
libgs = cdll.LoadLibrary(libgs)
del __win32_finddll
-121
==========================
`python-ghostscript`
==========================
---------------------------------------------------------------------
Python-Interface to the Ghostscript C-API
---------------------------------------------------------------------
:Author: Hartmut Goebel <h.goebel@crazy-compiler.com>
:Version: 0.6
:License: GNU Public License v3 (GPLv3)
:Homepage: https://gitlab.com/pdftools/python-ghostscript
`Ghostscript`__ is a well known interpreter for the PostScript
language and for PDF. This package implements a interface to the
`Ghostscript C-API`__ using `ctypes`__. Both a low-level and a pythonic,
high-level interface are provided.
__ http://www.ghostscript.com/
__ http://pages.cs.wisc.edu/~ghost/doc/cvs/API.htm
__ http://docs.python.org/library/ctypes.html
This package is currently tested only under GNU/Linux. Please report
whether it works in your environment, too. Thanks.
Example
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Here is an example for how to use the high-level interface of
`python-ghostscript`. This implements a very basic ps2pdf-tool::
import sys
import locale
import ghostscript
args = [
"ps2pdf", # actual value doesn't matter
"-dNOPAUSE", "-dBATCH", "-dSAFER",
"-sDEVICE=pdfwrite",
"-sOutputFile=" + sys.argv[1],
"-c", ".setpdfwrite",
"-f", sys.argv[2]
]
# arguments have to be bytes, encode them
encoding = locale.getpreferredencoding()
args = [a.encode(encoding) for a in args]
ghostscript.Ghostscript(*args)
Here an example for passing a string document to Ghostscript::
doc = b"""%!
/Helvetica findfont 20 scalefont setfont
50 50 moveto
(Hello World) show
showpage
quit
"""
import ghostscript
args = b"""test.py
-dNOPAUSE -dBATCH -dSAFER -sDEVICE=pdfwrite -sOutputFile=/tmp/out.pdf
-c .setpdfwrite""".split()
with ghostscript.Ghostscript(*args) as gs:
gs.run_string(doc)
More examples can be found in the `examples` subdirectory of the
distribution archive.
Requirements and Installation
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
:Please note: This package is meant for developers. Even if there are
some usable examples included, installations instructions are meant
for developers.
`python-ghostscript` requires
* `Python`__ 2.7 or higher (tested with Python 2.7, 3.4, 3.6 and 3.6)
* `setuptools`__ for installation (see below)
* `Ghostscript`__ Version 8.x or higher (tested with 9.x)
__ http://www.python.org/download/
__ http://pypi.python.org/pypi/setuptools
__ http://www.ghostscript.com/
Installing python-ghostscript
---------------------------------
Since this package is meant for developers, we assume you have
experience in installing Python packages.
`python-ghostscript` is listed on `PyPI (Python Package Index)`__, so
you can install it using `pip install ghostscript` as usual. Please
refer to the manuals of `pip` for further information.
__ http://pypi.python.org/pypi
Alternatively you my download and unpack the source package of
`python-ghostscript` from http://pypi.python.org/pypi/ghostscript and
run::
python ./setup.py install
.. Emacs config:
Local Variables:
mode: rst
ispell-local-dictionary: "american"
End:
Metadata-Version: 2.0
Name: ghostscript
Version: 0.6
Summary: Interface to the Ghostscript C-API, both high- and low-level, based on ctypes
Home-page: https://gitlab.com/pdftools/python-ghostscript
Author: Hartmut Goebel
Author-email: h.goebel@crazy-compilers.com
License: GPL 3.0
Download-URL: http://pypi.python.org/pypi/ghostscript
Description-Content-Type: UNKNOWN
Keywords: Ghostscript,PDF,Postscript
Platform: UNKNOWN
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: GNU General Public License (GPL)
Classifier: Natural Language :: English
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 2.7
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Dist: setuptools
==========================
`python-ghostscript`
==========================
---------------------------------------------------------------------
Python-Interface to the Ghostscript C-API
---------------------------------------------------------------------
:Author: Hartmut Goebel <h.goebel@crazy-compiler.com>
:Version: 0.6
:License: GNU Public License v3 (GPLv3)
:Homepage: https://gitlab.com/pdftools/python-ghostscript
`Ghostscript`__ is a well known interpreter for the PostScript
language and for PDF. This package implements a interface to the
`Ghostscript C-API`__ using `ctypes`__. Both a low-level and a pythonic,
high-level interface are provided.
__ http://www.ghostscript.com/
__ http://pages.cs.wisc.edu/~ghost/doc/cvs/API.htm
__ http://docs.python.org/library/ctypes.html
This package is currently tested only under GNU/Linux. Please report
whether it works in your environment, too. Thanks.
Example
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Here is an example for how to use the high-level interface of
`python-ghostscript`. This implements a very basic ps2pdf-tool::
import sys
import locale
import ghostscript
args = [
"ps2pdf", # actual value doesn't matter
"-dNOPAUSE", "-dBATCH", "-dSAFER",
"-sDEVICE=pdfwrite",
"-sOutputFile=" + sys.argv[1],
"-c", ".setpdfwrite",
"-f", sys.argv[2]
]
# arguments have to be bytes, encode them
encoding = locale.getpreferredencoding()
args = [a.encode(encoding) for a in args]
ghostscript.Ghostscript(*args)
Here an example for passing a string document to Ghostscript::
doc = b"""%!
/Helvetica findfont 20 scalefont setfont
50 50 moveto
(Hello World) show
showpage
quit
"""
import ghostscript
args = b"""test.py
-dNOPAUSE -dBATCH -dSAFER -sDEVICE=pdfwrite -sOutputFile=/tmp/out.pdf
-c .setpdfwrite""".split()
with ghostscript.Ghostscript(*args) as gs:
gs.run_string(doc)
More examples can be found in the `examples` subdirectory of the
distribution archive.
Requirements and Installation
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
:Please note: This package is meant for developers. Even if there are
some usable examples included, installations instructions are meant
for developers.
`python-ghostscript` requires
* `Python`__ 2.7 or higher (tested with Python 2.7, 3.4, 3.6 and 3.6)
* `setuptools`__ for installation (see below)
* `Ghostscript`__ Version 8.x or higher (tested with 9.x)
__ http://www.python.org/download/
__ http://pypi.python.org/pypi/setuptools
__ http://www.ghostscript.com/
Installing python-ghostscript
---------------------------------
Since this package is meant for developers, we assume you have
experience in installing Python packages.
`python-ghostscript` is listed on `PyPI (Python Package Index)`__, so
you can install it using `pip install ghostscript` as usual. Please
refer to the manuals of `pip` for further information.
__ http://pypi.python.org/pypi
Alternatively you my download and unpack the source package of
`python-ghostscript` from http://pypi.python.org/pypi/ghostscript and
run::
python ./setup.py install
.. Emacs config:
Local Variables:
mode: rst
ispell-local-dictionary: "american"
End:
{"classifiers": ["Development Status :: 4 - Beta", "Intended Audience :: Developers", "License :: OSI Approved :: GNU General Public License (GPL)", "Natural Language :: English", "Operating System :: OS Independent", "Programming Language :: Python", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3", "Topic :: Software Development :: Libraries :: Python Modules"], "description_content_type": "UNKNOWN", "download_url": "http://pypi.python.org/pypi/ghostscript", "extensions": {"python.details": {"contacts": [{"email": "h.goebel@crazy-compilers.com", "name": "Hartmut Goebel", "role": "author"}], "document_names": {"description": "DESCRIPTION.rst"}, "project_urls": {"Home": "https://gitlab.com/pdftools/python-ghostscript"}}}, "extras": [], "generator": "bdist_wheel (0.30.0)", "keywords": ["Ghostscript", "PDF", "Postscript"], "license": "GPL 3.0", "metadata_version": "2.0", "name": "ghostscript", "run_requires": [{"requires": ["setuptools"]}], "summary": "Interface to the Ghostscript C-API, both high- and low-level, based on ctypes", "version": "0.6"}
ghostscript/__init__.py,sha256=zlTi8OkNklYmB0yJLmgULcEpNepeKJj3Jj1huX6UHAE,5812
ghostscript/_errors.py,sha256=L4imjH7bO6YKfd6pieKhpsZYguvNkQRb9kx4BSRQBr8,5234
ghostscript/_gsprint.py,sha256=eImia_TYeNExLABPNaL4DBv_611WJ2UL1n9TovzfD2U,17218
ghostscript-0.6.dist-info/DESCRIPTION.rst,sha256=YQdIIkfTBERuUO1GWDeL7tf_PGYoYPs-dPnN3ouaaCA,3232
ghostscript-0.6.dist-info/METADATA,sha256=WTfOq_9p3e8Qml-oJz17-DT5GUQBCHH6vgas66ZTZDo,4143
ghostscript-0.6.dist-info/RECORD,,
ghostscript-0.6.dist-info/WHEEL,sha256=kdsN-5OJAZIiHN-iO4Rhl82KyS0bDWf4uBwMbkNafr8,110
ghostscript-0.6.dist-info/metadata.json,sha256=UR4KJZ6Cmcbca0OgPgYNRGoBl6yVaxOq_vLmEO_uQFE,1092
ghostscript-0.6.dist-info/top_level.txt,sha256=4oyhegeuLGZzu0jStqsvTLDipfr3KtKTqUbmgMT46H8,12
ghostscript-0.6.dist-info/zip-safe,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
Wheel-Version: 1.0
Generator: bdist_wheel (0.30.0)
Root-Is-Purelib: true
Tag: py2-none-any
Tag: py3-none-any

Sorry, the diff of this file is not supported yet

#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
ghostscript - A Python interface for the Ghostscript interpreter C-API
"""
#
# Copyright 2010-2018 by Hartmut Goebel <h.goebel@crazy-compilers.com>
#
# 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/>.
#
from __future__ import absolute_import
__author__ = "Hartmut Goebel <h.goebel@crazy-compilers.com>"
__copyright__ = "Copyright 2010-2018 by Hartmut Goebel <h.goebel@crazy-compilers.com>"
__licence__ = "GNU General Public License version 3 (GPL v3)"
__version__ = '0.6'
__all__ = ['Ghostscript', 'revision',
'GhostscriptError', 'PleaseDisplayUsage']
import atexit
import sys # :todo: remove, debugging only
from . import _gsprint as gs
GhostscriptError = gs.GhostscriptError
def PleaseDisplayUsage(Warning):
"""
This exception is raised when Ghostscript asks the application to
display the usage. The application should catch the exception an
print the usage message.
"""
pass
def revision():
"""
This function returns the revision numbers and strings of the
Ghostscript interpreter library as a dict. You should call it
before any other interpreter library functions to make sure that
the correct version of the Ghostscript interpreter has been
loaded.
"""
rev = gs.revision()
return dict((f, getattr(rev, f)) for f, _ in rev._fields_)
MAX_STRING_LENGTH = gs.MAX_STRING_LENGTH
class Ghostscript(object):
@staticmethod
def revision():
return revision()
def __init__(self, instance, args, stdin=None, stdout=None, stderr=None):
self._initialized = False
self._instance = instance
self._callbacks = None
if stdin or stdout or stderr:
self.set_stdio(stdin, stdout, stderr)
rc = gs.init_with_args(instance, args)
if rc == gs.e_Info:
raise PleaseDisplayUsage
self._initialized = True
if rc == gs.e_Quit:
self.exit()
def __enter__(self):
return self
def __exit__(self, *args):
self.exit()
def set_stdio(self, stdin=None, stdout=None, stderr=None):
"""Set stdin, stdout and stderr of the ghostscript interpreter.
The ``stdin`` stream has to support the ``readline()``
interface. The ``stdout`` and ``stderr`` streams have to
support the ``write()`` and ``flush()`` interface.
Please note that this does not affect the input- and output-
streams of the devices. Esp. setting stdout does not allow
catching the devise-output even when using ``-sOutputFile=-``.
"""
self._callbacks = (
stdin and gs._wrap_stdin(stdin) or None,
stdout and gs._wrap_stdout(stdout) or None,
stderr and gs._wrap_stderr(stderr) or None,
)
gs.set_stdio(self._instance, *self._callbacks)
def __del__(self):
self.exit()
def exit(self):
global __instance__
if self._initialized:
if __instance__:
#gs.exit(self._instance)
self._instance = None
self._initialized = False
def run_string(self, str, user_errors=False):
"""
Run the string ``str`` by Ghostscript
This takes care of Ghostscripts size-limitations and passes
the string in pieces if necessary.
"""
instance = self._instance
if len(str) < MAX_STRING_LENGTH:
gs.run_string(instance, str)
else:
gs.run_string_begin(instance)
for start in range(0, len(str), MAX_STRING_LENGTH):
gs.run_string_continue(instance,
str[start:start+MAX_STRING_LENGTH])
gs.run_string_end(instance)
def run_filename(self, filename, user_errors=False):
"""
Run the file named by ``filename`` by Ghostscript
"""
return gs.run_file(self._instance, filename, user_errors)
def run_file(self, file, user_errors=False):
"""
Read ``file`` and run the content by Ghostscript.
``file`` must already by opened and may by any file-like
object supporting the ``read()`` method.
"""
instance = self._instance
gs.run_string_begin(instance)
while True:
str = file.read(MAX_STRING_LENGTH)
if not str:
break
gs.run_string_continue(instance, str)
gs.run_string_end(instance)
__Ghostscript = Ghostscript
__instance__ = None
def Ghostscript(*args, **kw):
"""
Factory function for setting up a Ghostscript instance
"""
global __instance__, __object_count__
# Ghostscript only supports a single instance
if __instance__ is None:
__instance__ = gs.new_instance()
return __Ghostscript(__instance__, args,
stdin=kw.get('stdin', None),
stdout=kw.get('stdout', None),
stderr=kw.get('stderr', None))
def cleanup():
global __instance__
if __instance__ is not None:
gs.delete_instance(__instance__)
__instance__ = None
#atexit.register(cleanup)
"""
Definition of Ghostscript error codes
"""
#
# Copyright (C) 2010-2018 by Hartmut Goebel
#
# Based on iapi.h which is
# Copyright (C) 1989, 1995, 1998, 1999 Aladdin Enterprises. All rights reserved.
#
# 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/>.
#
__author__ = "Hartmut Goebel <h.goebel@crazy-compilers.com>"
__copyright__ = "Copyright 2010-2018 by Hartmut Goebel <h.goebel@crazy-compilers.com>"
__licence__ = "GNU General Public License version 3 (GPL v3)"
#
# A procedure that may return an error always returns
# a non-negative value (zero, unless otherwise noted) for success,
# or negative for failure.
# We use ints rather than an enum to avoid a lot of casting.
#
# ------ PostScript Level 1 errors ------
e_unknownerror = -1 # unknown error
e_dictfull = -2
e_dictstackoverflow = -3
e_dictstackunderflow = -4
e_execstackoverflow = -5
e_interrupt = -6
# We also need to define gs_error_interrupt, for gpcheck.h
gs_error_interrupt = e_interrupt
e_invalidaccess = -7
e_invalidexit = -8
e_invalidfileaccess = -9
e_invalidfont = -10
e_invalidrestore = -11
e_ioerror = -12
e_limitcheck = -13
e_nocurrentpoint = -14
e_rangecheck = -15
e_stackoverflow = -16
e_stackunderflow = -17
e_syntaxerror = -18
e_timeout = -19
e_typecheck = -20
e_undefined = -21
e_undefinedfilename = -22
e_undefinedresult = -23
e_unmatchedmark = -24
e_VMerror = -25
LEVEL1_ERROR_NAMES = ["unknownerror", "dictfull", "dictstackoverflow",
"dictstackunderflow", "execstackoverflow",
"interrupt", "invalidaccess", "invalidexit",
"invalidfileaccess", "invalidfont",
"invalidrestore", "ioerror", "limitcheck",
"nocurrentpoint", "rangecheck", "stackoverflow",
"stackunderflow", "syntaxerror", "timeout",
"typecheck", "undefined", "undefinedfilename",
"undefinedresult", "unmatchedmark", "VMerror"]
# ------ Additional Level 2 and DPS errors ------
e_configurationerror = -26
e_invalidcontext = -27
e_undefinedresource = -28
e_unregistered = -29
# invalidid is for the NeXT DPS extension.
e_invalidid = -30
LEVEL2_ERROR_NAMES = ["configurationerror", "invalidcontext",
"undefinedresource", "unregistered",
"invalidid"]
ERROR_NAMES = LEVEL1_ERROR_NAMES + LEVEL2_ERROR_NAMES
_PSEUDO_ERRORS = ['Fatal', 'Quit', 'InterpreterExit', 'RemapColor',
'ExecStackUnderflow', 'VMreclaim', 'NeedInput',
'NeedStdin', 'NeedStdout', 'NeedStderr', 'Info']
def error2name(ecode):
if ecode <= e_Fatal:
return _PSEUDO_ERRORS[-ecode-100]
else:
return ERROR_NAMES[-ecode-1]
# ------ Pseudo-errors used internally ------
#
# Internal code for a fatal error.
# gs_interpret also returns this for a .quit with a positive exit code.
#
e_Fatal = -100
#
# Internal code for the .quit operator.
# The real quit code is an integer on the operand stack.
# gs_interpret returns this only for a .quit with a zero exit code.
#
e_Quit = -101
#
# Internal code for a normal exit from the interpreter.
# Do not use outside of interp.c.
#
e_InterpreterExit = -102
#
# Internal code that indicates that a procedure has been stored in the
# remap_proc of the graphics state, and should be called before retrying
# the current token. This is used for color remapping involving a call
# back into the interpreter -- inelegant, but effective.
#
e_RemapColor = -103
#
# Internal code to indicate we have underflowed the top block
# of the e-stack.
#
e_ExecStackUnderflow = -104
#
# Internal code for the vmreclaim operator with a positive operand.
# We need to handle this as an error because otherwise the interpreter
# won't reload enough of its state when the operator returns.
#
e_VMreclaim = -105
#
# Internal code for requesting more input from run_string.
#
e_NeedInput = -106
#
# Internal code for stdin callout.
#
e_NeedStdin = -107
#
# Internal code for stdout callout.
#
e_NeedStdout = -108
#
# Internal code for stderr callout.
#
e_NeedStderr = -109
#
# Internal code for a normal exit when usage info is displayed.
# This allows Window versions of Ghostscript to pause until
# the message can be read.
#
e_Info = -110
#
# Define which error codes require re-executing the current object.
#
def ERROR_IS_INTERRUPT(ecode):
return ecode == e_interrupt or ecode == e_timeout
if __name__ == '__main__':
print(error2name(e_unknownerror) == "unknownerror")
print(error2name(e_VMerror) == "VMerror")
print(error2name(e_invalidid) == "invalidid")
print(error2name(e_VMreclaim) == "VMreclaim")
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
ghostscript._gsprint - A low-lewel interface to the Ghostscript C-API using ctypes
"""
#
# Copyright 2010-2018 by Hartmut Goebel <h.goebel@crazy-compilers.com>
#
# Display_callback Structure by Lasse Fister <commander@graphicore.de> in 2013
#
# 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/>.
#
from __future__ import absolute_import
__author__ = "Hartmut Goebel <h.goebel@crazy-compilers.com>"
__copyright__ = "Copyright 2010-2018 by Hartmut Goebel <h.goebel@crazy-compilers.com>"
__licence__ = "GNU General Public License version 3 (GPL v3)"
__version__ = "0.5dev"
from ctypes import *
import sys
from ._errors import *
MAX_STRING_LENGTH = 65535
DISPLAY_VERSION_MAJOR = 2
DISPLAY_VERSION_MINOR = 0
DISPLAY_VERSION_MAJOR_V1 = 1 # before separation format was added
DISPLAY_VERSION_MINOR_V1 = 0
# The display format is set by a combination of the following bitfields
# Define the color space alternatives
# DISPLAY_FORMAT_COLOR
DISPLAY_COLORS_NATIVE = (1<<0)
DISPLAY_COLORS_GRAY = (1<<1)
DISPLAY_COLORS_RGB = (1<<2)
DISPLAY_COLORS_CMYK = (1<<3)
DISPLAY_COLORS_SEPARATION = (1<<19)
DISPLAY_COLORS_MASK = 0x8000f
# Define whether alpha information, or an extra unused bytes is included
# DISPLAY_ALPHA_FIRST and DISPLAY_ALPHA_LAST are not implemented
# DISPLAY_FORMAT_ALPHA
DISPLAY_ALPHA_NONE = (0<<4)
DISPLAY_ALPHA_FIRST = (1<<4)
DISPLAY_ALPHA_LAST = (1<<5)
DISPLAY_UNUSED_FIRST = (1<<6) # e.g. Mac xRGB
DISPLAY_UNUSED_LAST = (1<<7) # e.g. Windows BGRx
DISPLAY_ALPHA_MASK = 0x00f0
# Define the depth per component for DISPLAY_COLORS_GRAY,
# DISPLAY_COLORS_RGB and DISPLAY_COLORS_CMYK,
# or the depth per pixel for DISPLAY_COLORS_NATIVE
# DISPLAY_DEPTH_2 and DISPLAY_DEPTH_12 have not been tested.
# DISPLAY_FORMAT_DEPTH
DISPLAY_DEPTH_1 = (1<< 8)
DISPLAY_DEPTH_2 = (1<< 9)
DISPLAY_DEPTH_4 = (1<<10)
DISPLAY_DEPTH_8 = (1<<11)
DISPLAY_DEPTH_12 = (1<<12)
DISPLAY_DEPTH_16 = (1<<13)
# unused (1<<14)
# unused (1<<15)
DISPLAY_DEPTH_MASK = 0xff00
# Define whether Red/Cyan should come first,
# or whether Blue/Black should come first
# DISPLAY_FORMAT_ENDIAN
DISPLAY_BIGENDIAN = (0<<16) # Red/Cyan first
DISPLAY_LITTLEENDIAN = (1<<16) # Blue/Black first
DISPLAY_ENDIAN_MASK = 0x00010000
# Define whether the raster starts at the top or bottom of the bitmap
# DISPLAY_FORMAT_FIRSTROW
DISPLAY_TOPFIRST = (0<<17) # Unix, Mac
DISPLAY_BOTTOMFIRST = (1<<17) # Windows
DISPLAY_FIRSTROW_MASK = 0x00020000
# Define whether packing RGB in 16-bits should use 555
# or 565 (extra bit for green)
# DISPLAY_FORMAT_555
DISPLAY_NATIVE_555 = (0<<18)
DISPLAY_NATIVE_565 = (1<<18)
DISPLAY_555_MASK = 0x00040000
# Define the row alignment, which must be equal to or greater than
# the size of a pointer.
# The default (DISPLAY_ROW_ALIGN_DEFAULT) is the size of a pointer,
# 4 bytes (DISPLAY_ROW_ALIGN_4) on 32-bit systems or 8 bytes
# (DISPLAY_ROW_ALIGN_8) on 64-bit systems.
# DISPLAY_FORMAT_ROW_ALIGN
DISPLAY_ROW_ALIGN_DEFAULT = (0<<20)
# DISPLAY_ROW_ALIGN_1 = (1<<20), # not currently possible
# DISPLAY_ROW_ALIGN_2 = (2<<20), # not currently possible
DISPLAY_ROW_ALIGN_4 = (3<<20)
DISPLAY_ROW_ALIGN_8 = (4<<20)
DISPLAY_ROW_ALIGN_16 = (5<<20)
DISPLAY_ROW_ALIGN_32 = (6<<20)
DISPLAY_ROW_ALIGN_64 = (7<<20)
DISPLAY_ROW_ALIGN_MASK = 0x00700000
class Revision(Structure):
_fields_ = [
("product", c_char_p),
("copyright", c_char_p),
("revision", c_long),
("revisiondate", c_long)
]
gs_main_instance = c_void_p
display_callback = c_void_p
class GhostscriptError(Exception):
def __init__(self, ecode):
# :todo:
Exception.__init__(self, error2name(ecode))
self.code = ecode
def revision():
"""
Get version numbers and strings.
This is safe to call at any time.
You should call this first to make sure that the correct version
of the Ghostscript is being used.
Returns a Revision instance
"""
revision = Revision()
rc = libgs.gsapi_revision(pointer(revision), sizeof(revision))
if rc:
raise ArgumentError("Revision structure size is incorrect, "
"requires %s bytes" % rc)
return revision
def new_instance(): # display_callback=None):
"""
Create a new instance of Ghostscript
This instance is passed to most other API functions.
"""
# :todo: The caller_handle will be provided to callback functions.
display_callback=None
instance = gs_main_instance()
rc = libgs.gsapi_new_instance(pointer(instance), display_callback)
if rc != 0:
raise GhostscriptError(rc)
return instance
def delete_instance(instance):
"""
Destroy an instance of Ghostscript
Before you call this, Ghostscript must have finished.
If Ghostscript has been initialised, you must call exit()
before delete_instance()
"""
return libgs.gsapi_delete_instance(instance)
c_stdstream_call_t = CFUNCTYPE(c_int, gs_main_instance, POINTER(c_char), c_int)
def _wrap_stdin(infp):
"""
Wrap a filehandle into a C function to be used as `stdin` callback
for ``set_stdio``. The filehandle has to support the readline() method.
"""
def _wrap(instance, dest, count):
try:
data = infp.readline(count)
except:
count = -1
else:
if not data:
count = 0
else:
count = len(data)
memmove(dest, c_char_p(data), count)
return count
return c_stdstream_call_t(_wrap)
def _wrap_stdout(outfp):
"""
Wrap a filehandle into a C function to be used as `stdout` or
`stderr` callback for ``set_stdio``. The filehandle has to support the
write() and flush() methods.
"""
def _wrap(instance, str, count):
outfp.write(str[:count])
outfp.flush()
return count
return c_stdstream_call_t(_wrap)
_wrap_stderr = _wrap_stdout
def set_stdio(instance, stdin, stdout, stderr):
"""
Set the callback functions for stdio.
``stdin``, ``stdout`` and ``stderr`` have to be ``ctypes``
callback functions matching the ``_gsprint.c_stdstream_call_t``
prototype. You may want to use _wrap_* to wrap file handles.
Note 1: This function only changes stdio of the Postscript
interpreter, not that of the devices.
Note 2: Make sure you keep references to C function objects
as long as they are used from C code. Otherwise they may be
garbage collected, crashing your program when a callback is made.
The ``stdin`` callback function should return the number of
characters read, `0` for EOF, or `-1` for error. The `stdout` and
`stderr` callback functions should return the number of characters
written.
You may pass ``None`` for any of stdin, stdout or stderr , in which
case the system stdin, stdout resp. stderr will be used.
"""
rc = libgs.gsapi_set_stdio(instance, stdin, stdout, stderr)
if rc not in (0, e_Quit, e_Info):
raise GhostscriptError(rc)
return rc
# :todo: set_poll (instance, int(*poll_fn)(void *caller_handle));
# :todo: set_display_callback(instance, callback):
def init_with_args(instance, argv):
"""
Initialise the interpreter.
1. If quit or EOF occur during init_with_args(), the return value
will be e_Quit. This is not an error. You must call exit() and
must not call any other functions.
2. If usage info should be displayed, the return value will be
e_Info which is not an error. Do not call exit().
3. Under normal conditions this returns 0. You would then call one
or more run_*() functions and then finish with exit()
"""
ArgArray = c_char_p * len(argv)
c_argv = ArgArray(*argv)
rc = libgs.gsapi_init_with_args(instance, len(argv), c_argv)
if rc not in (0, e_Quit, e_Info):
raise GhostscriptError(rc)
return rc
def exit(instance):
"""
Exit the interpreter
This must be called on shutdown if init_with_args() has been
called, and just before delete_instance()
"""
rc = libgs.gsapi_exit(instance)
if rc != 0:
raise GhostscriptError(rc)
return rc
def run_string_begin(instance, user_errors=False):
exit_code = c_int()
rc = libgs.gsapi_run_string_begin(instance, c_int(user_errors),
pointer(exit_code))
if rc != 0:
raise GhostscriptError(rc)
return exit_code.value
def run_string_continue(instance, str, user_errors=False):
exit_code = c_int()
rc = libgs.gsapi_run_string_continue(
instance, c_char_p(str), c_int(len(str)),
c_int(user_errors), pointer(exit_code))
if rc != e_NeedInput and rc != 0:
raise GhostscriptError(rc)
return exit_code.value
def run_string_end(instance, user_errors=False):
exit_code = c_int()
rc = libgs.gsapi_run_string_end(instance, c_int(user_errors),
pointer(exit_code))
if rc != 0:
raise GhostscriptError(rc)
return exit_code.value
def run_string_with_length(*args, **kw):
raise NotImpelmentedError('Use run_string() instead')
def run_string(instance, str, user_errors=False):
exit_code = c_int()
rc = libgs.gsapi_run_string_with_length(
instance, c_char_p(str), c_int(len(str)),
c_int(user_errors), pointer(exit_code))
if rc != 0:
raise GhostscriptError(rc)
return exit_code.value
def run_file(instance, filename, user_errors=False):
exit_code = c_int()
rc = libgs.gsapi_run_file(instance, c_char_p(filename),
c_int(user_errors), pointer(exit_code))
if rc != 0:
raise GhostscriptError(rc)
return exit_code.value
def set_visual_tracer(I):
raise NotImplementedError
# New device has been opened
# This is the first event from this device.
# int (*display_open)(void *handle, void *device);
c_display_open = CFUNCTYPE(c_int, c_void_p, c_void_p)
# Device is about to be closed.
# Device will not be closed until this function returns.
#int (*display_preclose)(void *handle, void *device);
c_display_preclose = CFUNCTYPE(c_int, c_void_p, c_void_p)
# Device has been closed.
# This is the last event from this device.
# int (*display_close)(void *handle, void *device);
c_display_close = CFUNCTYPE(c_int, c_void_p, c_void_p)
# Device is about to be resized.
# Resize will only occur if this function returns 0.
# raster is byte count of a row.
# int (*display_presize)(void *handle, void *device,
# int width, int height, int raster, unsigned int format);
c_display_presize = CFUNCTYPE(c_int, c_void_p, c_void_p,
c_int, c_int, c_int, c_uint)
# Device has been resized.
# New pointer to raster returned in pimage
# int (*display_size)(void *handle, void *device, int width, int height,
# int raster, unsigned int format, unsigned char *pimage);
c_display_size = CFUNCTYPE(c_int, c_void_p, c_void_p,
c_int, c_int, c_int, c_uint, POINTER(c_ubyte))
# flushpage
#int (*display_sync)(void *handle, void *device);
c_display_sync = CFUNCTYPE(c_int, c_void_p, c_void_p)
# showpage
# If you want to pause on showpage, then don't return immediately
# int (*display_page)(void *handle, void *device, int copies, int flush);
c_display_page = CFUNCTYPE(c_int, c_void_p, c_void_p,
c_int, c_int)
# Notify the caller whenever a portion of the raster is updated.
# This can be used for cooperative multitasking or for
# progressive update of the display.
# This function pointer may be set to NULL if not required.
# int (*display_update)(void *handle, void *device, int x, int y,
# int w, int h);
c_display_update = CFUNCTYPE(c_int, c_void_p, c_void_p,
c_int, c_int, c_int, c_int)
# Allocate memory for bitmap
# This is provided in case you need to create memory in a special
# way, e.g. shared. If this is NULL, the Ghostscript memory device
# allocates the bitmap. This will only called to allocate the
# image buffer. The first row will be placed at the address
# returned by display_memalloc.
# void *(*display_memalloc)(void *handle, void *device, unsigned long size);
c_display_memalloc = CFUNCTYPE(c_void_p, c_void_p, c_void_p, c_ulong)
# Free memory for bitmap
# If this is NULL, the Ghostscript memory device will free the bitmap
# int (*display_memfree)(void *handle, void *device, void *mem);
c_display_memfree = CFUNCTYPE(c_int, c_void_p, c_void_p, c_void_p)
# Added in V2 */
# When using separation color space (DISPLAY_COLORS_SEPARATION),
# give a mapping for one separation component.
# This is called for each new component found.
# It may be called multiple times for each component.
# It may be called at any time between display_size
# and display_close.
# The client uses this to map from the separations to CMYK
# and hence to RGB for display.
# GS must only use this callback if version_major >= 2.
# The unsigned short c,m,y,k values are 65535 = 1.0.
# This function pointer may be set to NULL if not required.
#
# int (*display_separation)(void *handle, void *device,
# int component, const char *component_name,
# unsigned short c, unsigned short m,
# unsigned short y, unsigned short k);
c_display_separation = CFUNCTYPE(c_int, c_void_p, c_void_p,
c_int, c_char_p, c_ushort, c_ushort, c_ushort, c_ushort)
class Display_callback_s (Structure):
_fields_ = [
# Size of this structure
# Used for checking if we have been handed a valid structure
# int size;
("size", c_int),
# Major version of this structure
# The major version number will change if this structure changes.
# int version_major;
("version_major", c_int),
# Minor version of this structure
# The minor version number will change if new features are added
# without changes to this structure. For example, a new color
# format.
#int version_minor;
("version_minor", c_int),
("display_open", c_display_open),
("display_preclose", c_display_preclose),
("display_close", c_display_close),
("display_presize", c_display_presize),
("display_size", c_display_size),
("display_sync", c_display_sync),
("display_page", c_display_page),
("display_update", c_display_update),
("display_memalloc", c_display_memalloc),
("display_memfree", c_display_memfree),
("display_separation", c_display_separation)
]
def set_display_callback(instance, callback):
rc = libgs.gsapi_set_display_callback(instance, callback)
if rc != 0:
raise GhostscriptError(rc)
return rc
def __win32_finddll():
try:
import winreg
except ImportError:
# assume Python 2
from _winreg import OpenKey, CloseKey, EnumKey, QueryValueEx, \
QueryInfoKey, HKEY_LOCAL_MACHINE
else:
from winreg import OpenKey, CloseKey, EnumKey, QueryValueEx, \
QueryInfoKey, HKEY_LOCAL_MACHINE
from distutils.version import LooseVersion
import os
dlls = []
# Look up different variants of Ghostscript and take the highest
# version for which the DLL is to be found in the filesystem.
for key_name in ('AFPL Ghostscript', 'Aladdin Ghostscript',
'GPL Ghostscript', 'GNU Ghostscript'):
try:
k1 = OpenKey(HKEY_LOCAL_MACHINE, "Software\\%s" % key_name)
for num in range(0, QueryInfoKey(k1)[0]):
version = EnumKey(k1, num)
try:
k2 = OpenKey(k1, version)
dll_path = QueryValueEx(k2, 'GS_DLL')[0]
CloseKey(k2)
if os.path.exists(dll_path):
dlls.append((LooseVersion(version), dll_path))
except WindowsError:
pass
CloseKey(k1)
except WindowsError:
pass
if dlls:
dlls.sort()
return dlls[-1][-1]
else:
return None
if sys.platform == 'win32':
libgs = __win32_finddll()
if not libgs:
raise RuntimeError('Can not find Ghostscript DLL in registry')
libgs = windll.LoadLibrary(libgs)
else:
try:
libgs = cdll.LoadLibrary("libgs.so")
except OSError:
# shared object file not found
import ctypes.util
libgs = ctypes.util.find_library('gs')
if not libgs:
raise RuntimeError('Can not find Ghostscript library (libgs)')
libgs = cdll.LoadLibrary(libgs)
del __win32_finddll