PostScript FAQ/Printable version


PostScript FAQ

The current, editable version of this book is available in Wikibooks, the open-content textbooks collection, at
https://en.wikibooks.org/wiki/PostScript_FAQ

Permission is granted to copy, distribute, and/or modify this document under the terms of the Creative Commons Attribution-ShareAlike 3.0 License.

General

General edit

The best way to learn any language is to use it. Pick an interesting problem (for instance quine) and try to code it in the new language. Download Ghostscript to test your work.

PostScript resources edit

There are several texts and resources on PostScript available free online. Some of these are.

Blue Book (PDF 0.9M), PostScript Language Tutorial and Cookbook, Adobe Systems, Addison-Wesley 1985, ISBN 0201101793 is the best introduction to PostScript language. PostScript operators are introduced in easy and well-paced way. Sample programs are easy to read and print beautiful pictures. The book describes only a fraction of level 1 PostScript. By itself it is not sufficient for professional work.

Green Book, (PDF 0.9M) PostScript Language Program Design, Adobe Systems, Addison-Wesley, 1988; ISBN 0201143968; shows how to use PostScript in real world situations. Among other things, it explains how to re-encode the font. This question is asked almost every month on comp.lang.PostScript. Although the book is based on level 1 PostScript, the good programming practices have not changed so much as the language itself.

White Book (PDF 0.5M) Adobe Type 1 Font Format, version 1.1, Addison-Wesley, 1990, ISBN 0201570440 describes the format of Type 1 font. The hinting rules description might have been accurate at the time of writing, but modern interpreters seem to use different algorithms. For instance, Adobe interpreters appear to auto-hint diagonal stems.

Red Book (PDF 7.6M) PostScript Language Reference Manual, Adobe Systems Addison-Wesley, 1999; ISBN 0201379228 912 pages, is the official description of PostScript language. Everything in the book is important; everything is explained only once. The Red Book is also available on paper for those who prefer to read in bed. An older version (dated 1999), without the necessity of registration in one of Adobe's partner programs, is available here.

Thinking in PostScript (PDF 0.8M) Glenn C. Reid, Addison-Wesley 1990; ISBN 0201523728 is a good introduction to PostScript. Many programmers prefer to think in terms of objects and methods but the book is available for free. Why not give it a try?

Adobe technical notes for developers cover many topics not included in the Red Book.

news://comp.lang.PostScript usenet group is the best place to discuss PostScript and Ghostscript issues.

freenode.net has a "##postscript" IRC channel to discuss PostScript.

"Mathematical Illustrations - A manual of geometry and PostScript", a book by Bill Casserman, contains many PostScript examples of all kinds.

Jim Land's Collection of PostScript and Ghostscript resources contains many links to PostScript resources available on the net.

Don Lancaster's PostScript Library contains dozens of original articles, utilities, and carefully selected links.

Ghostscript community site among other things hosts mailing lists, documentation archive, and Subversion repository with a handy web interface.

Ghostscript home page is an alternative distribution site for Ghostscript and related programs.

SourceForge is a primary Ghostscript distribution site. The bug tracker and CVS repository are no longer hosted there.

Ghostgum Software is a small software company located in Melbourne, Australia that is developing GSview GUI interface to Ghostscript, and RedMon Windows port redirector. The products and documentation are available for free download. The company also distributes Ghostscript on CD-ROM.

Artifex Software is the main developer and copyright holder of Artifex Ghostscript PostScript, PDF and PCL interpreter technologies. You need an Artifex license if you intend to redistribute Ghostscript technology with your proprietary products, or if you intend to use any source code from Ghostscript technologies within your proprietary products. Please contact them for details.

Unfortunately, many aspects of PostScript language are not documented at all. Ghostscript source code is the best reference to undocumented PostScript. For instance, do you know that Adobe implementations skip '\t', '\r', '\n', and ' ' after eexec but don't skip '\0' or '\f'. So the binary stream cannot start with some white space characters.

How to report a PostScript error? edit

A strange error happened... It crashed... I've done nothing... Help...

Unfortunately little can be done without the sample file and detailed description of the problem. Please generate and submit the PostScript file — that's what PostScript programmers know the best. If possible, create a small file: delete insignificant objects in your graphic application and choose small images.

Don't submit native application files. Most likely PostScript programmers don't have your applications. Quark alone has several mutually incompatible versions of QuarkXPress which cost from $500 to $2000 each. Some parts of the PS files come from a PostScript driver or PPD. It is very difficult to reproduce the user's environment exactly on the developer's computer.

Never send the file to discussion groups, unless the file is hand-made, ASCII only, and fits on the screen. Most readers don't need your file, many have slow modem connection, some even pay for the Internet traffic. Put the file on FTP or HTTP server and post the URL. If you don't have a site, you can get a free one from many free ISPs.

With a prior agreement, you can send small files ( < 7M ) by email. Normally ISP limits the size of a single message to 10M but base 64 encoding expands files 1.25 times. If you absolutely need to submit a big file (>300M), mail it on CD or DVD.

Bugs in Ghostscript should be entered directly into Ghostscript Bugzilla.

Who can help me? edit

This is a list of people and companies that are willing to answer user's questions about PostScript and related technologies and do custom software development.

GNU service directory is a list of people and companies who offer support services for GNU software, for a fee or in some cases at no charge. Many of them also offer support for non-GNU free software and general consulting.

Software Contractors' Guild is a resume database run by software contractors/consultants who want to expand the range of choices available to them and to their clients. About 50 people offer PostScript services.


Using PostScript

Using PostScript edit

Do I need a PostScript printer? edit

There are several situations when PostScript printer is desirable:

  • you need to print documents with placed EPS files
  • you receive print jobs from 3rd parties and need a portable page description language
  • you expect to print variable content documents
  • desktop printer serves as a cheap proofer for a more expensive printer or imagesetter
  • vector page description is much shorter than the raster image of the page
  • you run Unix-like system where PostScript language serves as a printer API.

Software RIP with a non-PostScript printer is becoming a good alternative to a PostScript printer. Unlike built-in RIP the software and hardware can be easily upgraded. The host OS also provides a better debugging environment.

How to create a PS file? edit

PostScript is a low level page description language. The PostScript graphic model is based on presentation elements: lines, curves, characters, images. There is no notion of words, paragraphs, justification, footnotes, etc. Most authors prefer to work on the higher level and generate presentation formats (PostScript, PDF, PCL, etc.) from the high level page description.

TeX is a typesetting program designed for high-quality composition of material that contains a lot of mathematical and technical expressions. It has been adopted by many authors and publishers who generate technical books and papers. It was created by Professor Donald Knuth of Stanford University, originally for preparation of his book series The Art of Computer Programming.

groff (GNU troff) software is a typesetting package which reads plain text mixed with formatting commands and produces formatted output.

PostScript printer drivers on Mac OS and Microsoft Windows can generate PostScript file from the incoming GDI calls. So every application that prints can also generate PostScript. However the set of graphic primitives in the file will be limited by the GDI graphic model. Most graphic editors and DTP applications bypass GDI and generate PostScript directly. This helps to generate better PostScript and provides more flexible graphic model to the application.

Sometimes it is necessarily to create or modify PS files by hand. PostScript files can be big and contain binary data. The text editor should not expand tabs or normalize line ending. emacs is a good choice because it is extensible and includes a PostScript major mode.

How to send a PS file to a printer? edit

On a Unix-like system you can use Page Template:Mono/styles.css has no content.lpr:

lpr -S computer_name -P queuename filename.ps

On Microsoft Windows you can send the file to a printer as:

copy /b filename.ps lpr1

or

copy /b filename.ps \\computer_name_or_ip\printersharename

Some of the printers also support Page Template:Mono/styles.css has no content.lpr protocol.

PrintFile is a freeware GUI Windows program that copies files the system print queue. It can also pick pages from the DSC-conforming PostScript file.

On Classic Mac OS, you can drop the file on the printer icon.

What is the best way to view a PS file on the screen? edit

PostScript file is designed for sequential printing - images are often stored as inline streams, page size and resolution is a part of page description.

The viewer is expected to browse the document in random order and magnification. This can be achieved by converting the PostScript to an internal form that enables direct access to page elements and fast clipping of invisible objects. None of the PostScript viewers work this way.

GSview is a free graphical interface for Ghostscript developed by Russel Lang at Ghostgum Software. The page selection is implemented through DSC processing; zoom is implemented by re-interpretation of the page. GSview is available for Win32, Win32s, OS/2 and GNU/Linux. Older versions are available for Win16. There are other graphical X-Window front ends for Ghostscript - examples are mgv, Moonshiner and Okular.

PostScript can be easily converted to PDF using Ghostscript, ps2pdf online, Distiller, PDFCreator and a few of other programs. There are many more PDF viewers than PS viewers. Furthermore PDF viewers often are more user friendly than most PS viewers, the most convenient way to view a PS file is to convert it first into a PDF file. The most popular free PDF viewers are Adobe Reader, Evince, Foxit Reader, MuPDF, Okular, PDF-XChange Viewer, Sumatra PDF and Xpdf.

How to send a binary PostScript file to an ASCII-only printer? edit

Many network printers don't accept PS files containing binary data.

Sometimes it is impossible to re-create the file as 7-bit ASCII but any file is easy to convert to ASCII stream and execute it through the corresponding decoding filter. The following script converts standard input to hexadecimal stream and adds the decoding code. All DSC comments will be hidden but most printers ignore them anyway. The script was tested on bash and GNU/Linux systems.

#! /bin/sh
echo '%!'
echo 'currentfile /ASCIIHexDecode filter cvx exec'
od -A n -v -t x1
echo '>'

The version of the script for MS-DOS and Windows has to read '>' character from itself because echo ">" prints ">" (with the quotes).

@echo off
rem ">"
echo %%!
echo currentfile /ASCIIHexDecode filter cvx exec
od -A n -v -t x1
od -A n -v -t c -j 16 -N 1 %0

od (octal dump) comes from the GNU Textutils package. It is available on all stock Unix-like systems (including macOS) and can be installed on Windows with Cygwin or MinGW packages.

PostScript utilities can be easily programmed using the PostScript language. The following program reads the input file or standard input, compresses it, optionally converts it using ASCII85 encoding, and writes to output file or standard output. The program is run by Ghostscript using:

 gs -q [-dASCII] [-dLEVEL3] -- encode.ps [INFILE [OUTFILE]]

Where:

-q suppresses writing of copyright information to stdout
-dASCII selects ASCII85 encoding
-dLEVEL3 selects Flate encoding introduced in level 3
encode.ps is the program
INFILE is input file, defaults to stdin
OUTFILE is output file, defaults to stdout
%!
% encode.ps - compress and encode PS file to reduce upload time.
% This won't work if the file contains multiple jobs separated by ^D
%
/stderr (%stderr)(w) file def
/error { stderr exch writestring } bind def
/closetarget <</CloseTarget true>> readonly def
%
/openfile  % fname mode -> file
{ { file } stopped
    { exch (Cannot open file: ) error error (w) eq { (for writing\n) } { (for reading\n) } ifelse error
      flush quit
    }
  if
} bind def
%
/main      % - -> -
{ mark shellarguments
    { counttomark 2 le
        { counttomark
            { { (%stdin)(r) file (%stdout)(w) file }
              { (r) openfile (%stdout)(w) file }
              { (w) openfile exch (r) openfile exch }
            }
          exch get exec dup                   % input output output
          //systemdict /ASCII .knownget dup { true eq and } if
            { //closetarget /ASCII85Encode filter
              (/ASCII85Decode filter)
            }
            { () }
          ifelse
          exch                                % input output () output
          //systemdict /LEVEL3 .knownget dup { true eq and } if
            { //closetarget /FlateEncode filter exch
              (/FlateDecode filter)
            }
            { //closetarget /LZWEncode filter exch
              (/LZWDecode filter)
            }
          ifelse
          concatstrings                       % input output output ()
          2 index (%!\ncurrentfile) writestring
          2 index exch writestring
          exch ( cvx exec\n) writestring
          exch 61440 string                   % output input buf
            { 3 copy readstring pop           % output input buf output buf
              dup () eq { pop pop exit } if
              writestring
            }
          loop
          pop closefile closefile false
        }
        { (Incorrect number of file name arguments.\n) error true
        }
      ifelse
    }
    { (Missing '--' preceding encode.ps\n) error true
    }
  ifelse
    { (Usage: gs -q -dASCII -dLEVEL3 -- encode.ps INFILE OUTFILE\n) error flush
    }
  if
} bind def
%
main clear quit

If needed, DSC processing can be done before downloading the file to the printer. Development of a DSC-aware ASCII85-based converter is left for the exercise of the reader.

How to print an EPS file? edit

Encapsulated PostScript, or EPS, files are usually meant for inclusion in printable PostScript or other EPS files. Unlike the printable PostScript they can have:

  • showpage operator not included
  • image shifted outside of the printable area
  • image size too big or too small
  • PC-style header and preview

Thus, sending EPS files to a PostScript printer directly may cause a PostScript error or only page to be printed.

The standard way is to place EPS in the page in a graphic design application and print.

In order to directly print an EPS file, you need to add a PS header that does all the necessary adjustments.

cat header.ps file.eps | lpr

A suitable header is given as an example on the Page Template:Mono/styles.css has no content.net.anastigmatix.Import resource page.

How to check whether a PostScript file is valid ? edit

Send the file to a PostScript interpreter. If you like the results the file is valid. PostScript interpreters include:

There are others of course, but these are the simplest/cheapest to get hold of.

In fact this will check correctness of the PostScript program only on the interpreter where it has been tested. Different interpreters provide very different execution environment that can make PS program take a different branch.

PostScript program can produce unexpected output without reporting any PostScript errors. In the mission-critical situation a proof page printed on the laser printer and signed by the designer is mandatory.

How to count pages in a PS file? edit

Interpret the file using bbox device and count HiResBoundingBox lines.

gs -q -dNOPAUSE -dBATCH -sDEVICE=bbox foo.ps 2>&1 | grep -c HiResBoundingBox

Somewhat faster is also the command

yes | gs -q -dBATCH -sDEVICE=nullpage foo.ps | grep -c showpage

Assuming the document is DSC-conforming one can count Page Template:Mono/styles.css has no content.%%Page comments directly in the document.

grep -c %%Page: file.ps

How to determine which pages are color and which are monochrome? edit

First, you need to decide what makes the page a color page. Probably, monochrome page has zero density of CMY components. To check this using Ghostscript you need to select a true color CMYK device, install correct CRD and rasterize the file.

The page is a color page if any pixel has non-zero components in CMY planes.

How to print only some pages from a PS file? edit

DSC (Document Structure Convention) was intended to provide an easy way to parse the PostScript document, rearrange pages, add missing fonts, substitute images, etc. Although most programs generate DSC comments few programs use them. It appears that correctness of DSC comments has been never tested even by major vendors.

Sometimes the document claiming DSC conformance fails with PostScript errors after modification. Even worse the pages can be spoiled in some subtle way. For instance, some characters of the incrementally downloadable font may be silently replaced with a default character.

Page selection based on DSC comments is used by PrintFile and GSview.

PDF can serve as a convenient intermediate format esp. when page extraction is performed more than once. You can use Ghostscript to convert the file to PDF and extract a range of pages as following:

ps2pdf input.ps output.pdf
gs -dFirstPage=1 -dLastPage=2 output.pdf

Occasionally, other graphic formats can work better than PDF. The author once wrote bilist.cpp to place two A5 pages on a single A4 page and rearrange pages into signatures for some old PCL printer.

How to rearrange pages of a PS file for printing a brochure? edit

There are several ways to solve this problem. Every approach has its advantages.

Direct manipulation preserves most of PS structure and takes least processor time. Unfortunately, it is only applicable for DSC-conforming PostScript files. Although most DSC files generated by mainstream applications claim DSC conformance few have been tested as such. For instance, Microsoft PS driver generates non-conforming files by default.

Page Template:Mono/styles.css has no content.psselect from psutils can select and reorder pages in the DSC-conforming PS file.

Conversion to raster image is a simple and reliable approach. For instance bilist.cpp extracts pages from the PCL file, reorders pages into signatures, and places them 2-up. Ghostscript can be used for PostScript to PCL conversion.

Conversion to PDF greatly simplifies further document processing. Pages in PDF file can be extracted and printed in any size or order. The PostScript file can be converted to PDF using several applications. For instance, Ghostscript

ps2pdf input.ps output.pdf

To extract a range of pages from a PDF file into another PDF file use

ps2pdf -dFirstPage#111 -dLastPage#666 input.pdf output.pdf

To extract a range of pages from a PDF file and convert to PS file use:

ps2ps -dFirstPage#111 -dLastPage#666 input.pdf output.ps

It is always safe to concatenate PDF files as following

gs -dNOPAUSE -dBATCH -sDEVICE=pdfwrite -sOutputFile=file.pdf \
   -c save pop -f file1.dsc file2.dsc file3.dsc ...

The methods above are sufficient to rearrange pages in any order but complex jobs can be done more efficiently. The PDF file can be convertrd to a simple DSC-conforming PS file.

pdf2dsc source.pdf output.dsc

The output file will be very simple, because all the complexity is hidden inside Ghostscript libraries. The format is trivial to modify using any DSC utility, text editor, or script.

%!PS-Adobe-3.0
%...
/Page null def/Page# 0 def/PDFSave null def/DSCPageCount 0 def
/DoPDFPage {dup /Page# exch store pdfgetpage pdfshowpage } def
GS_PDF_ProcSet begin pdfdict begin
file.pdf) (r) file { DELAYSAFER { .setsafe } if } stopped pop
pdfopen begin
%%Page: 1 1
1 DoPDFPage
%%Page: 2 2
2 DoPDFPage
%%Trailer
currentdict pdfclose end end end
%%EOF

Updated file can be converted back to PDF.

ps2pdf source.dsc result.pdf

The DSC file uses GS libraries, which is fine if the DSC file is fed to Ghostscript only. To generate a portable PS file convert it back to PS.

Why does my PS driver generate color drawings but grayscale images? edit

When the driver generates PostScript stream for monochrome printer it often converts color images to grayscale for better transmission time, faster rendering, and lower resource usage. Conversion of vector objects to grayscale doesn't save much space or time. So the driver leaves it to the PostScript interpreter.

This problem often happens when the job is printed to Generic PostScript printer driver. Generic driver is not the best one. It is limited to the common subset of PostScript language available on most printers. It is monochrome, has small choice of media, fonts, no special features.The PostScript file from Generic driver will print on wide variety of printers but many features will be missing.

Although it appears like every printer uses a special driver it is the same driver configured for different printers. The driver takes configuration parameters from PPD file. When possible the native PPD file should be used. The Acrobat Distiller PPD is a good choice to generate a color PostScript file free of vendor-specific features.

How to recombine plates in preseparated PostScript file? edit

It is very simple to rasterize the pages and recombine the pages into the composite file. Rasterization can be done at 8 bit per plane or 1 bit per plane depending whether any color correction is desired for the composite image.

Merging the planes on vector level is much more difficult. The only known tool for this job is the Seps2Comp Acrobat plug-in from Creo (now discontinued and unsupported). The PostScript file can be converted to PDF using a number of programs including Ghostscript and Acrobat Distiller.

How to remove black frames around n-up pages? edit

Windows driver generates black frames around virtual pages when it does n-up printing. The frames are drawn in nupshowpage procedure. To remove the frames this procedure must be modified. On level 3 interpreters Hack-MSDriver-n-up IdiomSet can identify and replace this procedure when the job file is loaded by the interpreter. No modification of the job file is needed. To activate the replacement you need to copy the idiom file to /Resource/IdiomSet/ directory on the printer or host-based interpreter. The PostScript root directory on a host-based interpreter likely to be different from the system root. For one-time replacement you can also prepend the IdiomSet file to the job file.

For level 1 and 2 interpreters one has to remove framenup { ... } if fragment from the job file itself using any text editor.

%!PS-Adobe-3.0
%%Title: Hack-MSDriver-n-up
% Remove black frame around n-up pages generated by MS Driver
%%VMusage: 0 0
%%VMlocation: global
%%EndComments
%%BeginResource: IdiomSet Hack-MSDriver-n-up
currentuserparams /IdiomRecognition get
<</IdiomRecognition false>> setuserparams
currentglobal true setglobal
/Hack-MSDriver-n-up
<< 8 dict begin
   /; /grestore load def
   /V /div load def
   /@ /dup load def
   /~ /exch load def
   /rs /rectstroke load def
   /! /pop load def
   /? /ifelse load def
   /+ /translate load def
   /nupshowpage
     [ { ; $m concat
         framenup
           { pagemarg_nup 2 V nups V
             @ $m idtransform abs neg ~ abs neg ~
             paperw_nup paperh_nup rs
           }
         if
         /pgx_nup pgx_nup 1 add
         @ nx_nup eq
           { ! 0 store paperw_nup 1 nx_nup sub mul
             /pgy_nup pgy_nup
             1 add @ ny_nup eq
               { ! 0 store paperh_nup 1 ny_nup sub mul
               }
               { store paperh_nup
               }
             ?
           }
           { store paperw_nup 0
           }
         ? + $m matrix invertmatrix concat startpage
       } bind
       { ; $m concat
         /pgx_nup pgx_nup 1 add
         @ nx_nup eq
           { ! 0 store paperw_nup 1 nx_nup sub mul
             /pgy_nup pgy_nup
             1 add @ ny_nup eq
               { ! 0 store paperh_nup 1 ny_nup sub mul
               }
               { store paperh_nup
               }
             ?
           }
           { store paperw_nup 0
           }
         ? + $m matrix invertmatrix concat startpage
       } bind
     ]
   end
>> /IdiomSet defineresource pop
setglobal <</IdiomRecognition 3 -1 roll>> setuserparams
%%EndResource
%%EOF

How to print A4 on US Letter or vice versa? edit

To be written.

The document can be scaled or just shifted.

psresize -PA4 -pletter a4.ps letter.ps
psnup -pletter -Pa4 a4file.ps letterfile.ps

Fix pagedevice, policy 3,

How to extract figures from PostScript files? edit

Figures in PostScript document are often included as EPS files and can be easily extracted with a text editor. In the DSC-conforming document the EPS file is framed by using a text editor.

%%BeginDocument
...
%%EndDocument

Don't forget that EPS files can be nested.

EPS files extracted from the PostScript file don't have a preview, which can be re-generated with Ghostscript.

How to change color PostScript to black-and-white?* edit

If you can run Perl, look for bw_convert, a tiny perl script that will change every RGB color declaration in a PostScript file to a black or grey value. Simply enough, it replaces "setrgbcolor" with "pop pop pop 0 setgray". The script can be found at bw_convert. The script author is not documented on that site. However, this script is really an excellent example of how not to do things; the author has not really grasped that PostScript is a programming language, and that simple lexical changes will often fail, while adding an extra line of code at the start would be more effective. The script also does not touch images, CMYK data, or level 2 color operators.

A similar thing can be done by adding the following line at the beginning of a PostScript file:

/setrgbcolor {0.11 mul 3 1 roll 0.59 mul 3 1 roll 0.30 mul add add setgray} def

It will overwrite setrgbcolor with setgray and calculate a grayscale color. Still this will not affect images and might not change everything that you wanted to change. There also could be other problems so no warranty on that.

How to tweak RGB to CMYK conversion but leave other objects intact? edit

Level 3 PostScript has a powerful method for tweaking correction of device-dependent colors to device-independent colors: /UseCIEColor page device key and DefaultGray, DefaultRGB, DefaultCMYK color spaces.

When UseCIEColor flag is on, grayscale, RGB, and CMYK colors are interpreted as the colors in DefaultGray, DefaultRGB, and DefaultCMYK color spaces. It is little known that an array form of device color spaces ( e.g. [DeviceCMYK]) can be defined as a Default* resource effectively disabling the corresponding conversion.

Conversion of CMYK to device-independent colors is often undesirable because of the loss of black generation information.

How to get date and time? edit

Built-in access to the date and time is with currentdevparams and setdevparams on the %Calendar% device, which appeared in the PostScript Language Reference Manual version 2012 supplement for PostScript LanguageLevel 2. The following code will write the date and time to standard output:

(%Calendar%) /IODevice resourcestatus {
  pop pop (%Calendar%) currentdevparams
  dup /Running get {
    dup /Year get 4 string cvs print (-) print
    dup /Month get 2 string cvs print (-) print
    dup /Day get 2 string cvs print ( ) print
    dup /Hour get 2 string cvs print (:) print
    dup /Minute get 100 add 3 string cvs 1 2 getinterval print (:) print
    /Second get 100 add 3 string cvs 1 2 getinterval print (\n) print
  } {
    (Clock/calendar is present but not running.\n) print
  } ifelse
} {
  (No clock/calendar present.\n) print
} ifelse

The standard does not provide for timezone information and the clock is generally set for local time. Its range extends to 2079. If the interpreter is running on a host operating system, the OS is likely to determine whether setdevparams can actually set the clock.

A host-based PostScript interpreter can access the file system, including named pipes and devices, so possibilities are endless. This example was tested on GNU+Linux using the specific interpreter Ghostscript.

Type the following on one terminal:

mkfifo foo
while true; do date >foo; done

Run Page Template:Mono/styles.css has no content.gs -dNODISPLAY on another terminal in the same directory, then type

/t { (foo)(r) file closefile (foo)(r) file dup
    28 string readstring pop = closefile} def

Now, typing t at the Ghostscript prompt shows the current time, using the host OS date command instead of the %Calendar% device.

PostScript has been used to implement an HTTP server.


Programming PostScript

Programming PostScript edit

How to edit a PS file? edit

Few people want to edit HPGL or PCL. PostScript is yet another control language used by some laser printers. In most cases PostScript file is algorithmically derived from some human-readable document. Get the original document, if possible.

Visual editing requires interpretation of the PS file, editing of the objects, and generation of a new PostScript file. Few applications support all features of PostScript graphic model. Unsupported features will be lost or approximated. Being a programming language PostScript can take different branches depending on the execution environment. Untaken branches will be discarded by the interpreter leaving no trace in the editor. When the printer driver generates PS file it doesn't care about preserving high-level structure. It can be very difficult to do something beyond fixing a spelling error or changing a page number.

Many mainstream graphic editors can import PS files. The quality of the built-in interpreters varies and is often limited to level 1. PDF import filter tend to work better; try to convert the PS file to PDF first.

If the PS file has too many primitives unsupported by the visual editor, pstoedit utility from Ghostscript can be used to reduce PostScript file to a sequence of path operations.

Tailor, from EnFocus Software, seems to be the only proprietary PostScript editor available. (It was discontinued long ago). There is also a software from CGS called PDF Tuner that can edit both PostScript and PDF files. This Software is constantly developed.

Manual editing requires good knowledge of PostScript language and a robust text editor. Occasionaly users make PS files over 100M long. The files often contain binary data; sometimes they depend on the exact size of data.. The text editor shouldn't expand tabs or normalize line ends. Hexadecimal view of the file can be handy.

Redefinition of operators and procedures is a powerful technique to alter the behaviour of a PS file. New code can be included into the RIP startup script, copied by the driver from PPD, or added directly into the file by an input filter. token operator helps to take away the control from the PostScript interpreter when operator redefinition doesn't work.

Idiom recognition is an automated technique to patch a PS procedure when it is bound. Although it was designed to add smooth shading to legacy PostScript programs it can be also used to fix bugs.

How to create a PS form and populate it from a database? edit

Fixed format forms can be created in any graphic editor and contain any presentation graphics. The variable content fields can be reserved using placeholder EPS files.

The placeholder EPS files can be replaced with variable content using standard Unix text tools. For many years a similar technique has been used in OPI workflow.

Alternatively, the placeholder EPS files can be made smart and print themselves. Variable content can be retrieved from PostScript VM or external files.

Variable format documents need text reflow and re-pagination. You have the option of using available resources for direct PostScript text formatting, or creating the report in a higher level page layout language (TeX, groff) and converting it to PostScript or PDF.

In most cases it is impossible to replace words in a PostScript document harvested from a standard PostScript driver. Drivers can fragment the word for kerning without xshow, use hexadecimal strings, or convert the line of text to a sampled image. The latter is a common way to print Asian fonts on Roman printers.

How to concatenate several PS files? edit

Contrary to the popular belief PostScript files cannot be concatenated to get the combined result.

 # won't work
 cat page1.ps page2.ps page3.ps > threepages.ps

Entering the files as a separate Ghostscript arguments won't help either.

 # won't work
 gs -sDEVICE=pswrite -sOutputFile=threepages.ps page1.ps page2.ps page3.ps

PostScript programs change the state of the PostScript interpreter and these changes must be undone before the next program runs. First, write the following header.

 %!
 /begin_file
  { /save_state save def  % save state of PS interpreter
    currentfile
    0 (% $$$ EOF Mark $$$) /SubFileDecode filter cvx exec % safequard against flushfile, etc.
  } bind def
 /end_file
  { clear cleardictstack  % clear after the file
    save_state restore    % restore the state
  } bind def

Include every PostScript file in the following wrapper and append them to the header.

 begin_file
 % Include your file here.
 % $$$ EOF Mark $$$       % don't delete this line
 end_file

The result won't be DSC-conforming even if the original files are.

Composition of EPS files is done by placement of the files into a container EPS file.

PostScript interpreters that work in a job server mode (most printers, Ghostscript 8.50 or higher with -dJOBSERVER) treat multiple jobs delimited with ^D character and piped to the input stream as independent jobs.

In general it is impossible to concatenate several PS programs to get the combined result. The following program will defeat all attempts to append something to it. Most commonly such techniques can be found in OCF font installers.

 systemdict begin (%stdin) (r) file flushfile

How to print accented characters? edit

Single byte PS fonts can include many glyphs, but only 256 of them can be accessed at the same time. The 256 element array mapping a character code to the glyph name is known as an encoding vector. The PostScript language has several built-in encoding vectors. You can (and should always) re-encode your fonts. The ISOLatin1Encoding is probably a good start. To re-encode the font, what you need to do is:

/Courier findfont               % load the font, for instance, Courier
0 dict copy begin               % copy it to a new dictionary
/Encoding ISOLatin1Encoding def % replace encoding vector
/MyCourier /FontName def        % replace font name
currentdict end
dup /FID undef                  % remove internal data
/MyCourier exch definefont pop  % define the new font 

Re-encoded fonts can be used in the same way as any other fonts.

There are several ways to print more than 256 glyphs at a time.

  • Create a few re-encoded fonts and select them when needed.
  • Use glyphshow for rare characters
  • Make OCF fonts from several re-encoded fonts. OCF supports every imaginable encoding scheme.
  • Make a composite font from CMap and Font or CIDFont resources.

How to justify text in PostScript? edit

The common approach is to do text formatting in an application. The application emits PostScript code reflecting the final format - now a simple question of dumping things at x, y coordinates. If an application overrides the default interword/interletter spacing (say, for justification or kerning), it should use PostScript's ashow, widthshow, awidthshow, kshow, xshow, yshow, or xyshow operators, which take an intact text string and a separate specification for positioning the elements. The sloppy alternative, just using show on individual letters and small word fragments with movetos in between, is a hindrance for text extraction programs and distillers.

To perform common functions of text formatters, such as hyphenation, multi-column text, footnotes, bibliography, glossary, etc., in PostScript itself requires implementing suitable algorithms in PostScript and supplying them along with the file to be rendered, either included in the file or downloaded in advance. Existing implementations include David Byram-Wigfield's TinyDict, Graham Freeman's Quikscript, and Don Lancaster's Gonzo Utilities. All three are quite full-featured, with justification, columns, pagination, and many other features. Simpler building blocks include Chapman Flack's Markup, which can be used as a front end to those, or to do simple left/center/right unfilled/unjustified text setting on its own, and Hyphenate, an implementation of the TeX hyphenation algorithm, for which many language-specific patterns have been compiled. Collectively, these approaches that do the bulk of the computation in PostScript itself can be called (Byram-Wigfield's term) direct PostScript, and the Anastigmatix direct PostScript page further describes and compares them.

Automatic kerning requires information that is in the Adobe Font Metrics (AFM) files that come with most fonts, so to do it in PostScript would require downloading also the appropriate AFM files and some PostScript code to parse them (the syntax is simple). No direct PostScript resource that does this seems currently available. All of the existing systems do permit manual kerning, which is usually adequate as kerning is most important for large display type, accounting for a small fraction of a typical document.

Designs are not limited to two approaches, all formatting in the application emitting pure PostScript only or full-fledged direct PostScript. The first approach tends to save compute time on the printer at the expense of emitting large, uneditable PostScript files and longer transmission times to the printer, and direct approaches can have compact, editable files (with fixed prologs of implementation code that can be downloaded once in advance) and do more computation on the printer. Most applications choose a compromise, doing some of the work in the application and including prologs in the emitted PostScript that provide procedures to finish the work on the printer itself. It would even be possible to design an application that used one of the existing direct PostScript resources as its prolog, and emitted the document in that form.

How to place several copies of a picture? edit

The picture can be a sampled image or EPS file.

PostScript always reads the standard input stream forward. There is no way to reposition the file or push characters back. Next picture need a new copy of data. To reuse the picture we need to copy the data from the input stream to the reusable object.

Short data can be stored in a PostScript string, but the string length is limited to 64K-1 . More data can be stored as an array of strings. The length of array is also limited to 64K-1 but this is enough to exhaust the memory on most printers. In fact low end printers can have as little as 256K of free memory.

Encoding filters can be used to compress picture data. In level 3 PostScript most encoding filters are optional.

PostScript level 3 introduces reusable streams. They cache the input data and can be repositioned after reading to the end of the file. On disk-less printers reusable streams are implemented in memory file system.

Some printers and most host-based RIP's have writeable file systems.

To avoid multiple rendering PostScript level 2 introduced forms. It is a wrapper around a procedure that hints PostScript interpreter how to cache rendering results. The form procedure can be executed many times and need reusable data source. Forms are rarely used and many Adobe OEM choose very small default size for the form cache.

How to redefine an operator? edit

The simpliest approach is to use bind operator.

 /foo { bar } bind def

This approach is not recommended in production environment where foo can be already redefined as a procedure. The following approach works in all cases.

 /baz /foo load def
 /foo { baz bar } bind def

Ghostscript also provides implementation-specific ways of operator redefinition. See the comments to odef operator in Ghostscript sources.

Good redefinition should preserve as many features of the original operator as possible. The following simple redefinition of halftone operators can cause several unexpected problems.

 /sethalftone { pop } bind def
 /setscreen { pop pop pop } bind def
 /setcolorscreen { 12 { pop } repeat } bind def

First, halftone can read data from the current file. Second, differences in error processing may be significant. The stock installation of an early version of Mac OS X generated the following code:

 featurebegin { 30 60 setscreen % no function!
 } featurecleanup

The redefinitions above would smash the stack and cause a PostScript error regardless of featurecleanup. Here are better redefinitions

 /sethalftone_orig /sethalftone load def
 /setscreen_orig /setscreen load def
 /setcolorscreen_orig /setcolorscreen load def
 /sethalftone { gsave sethalftone_orig grestore } bind def
 /setscreen { gsave setscreen_orig grestore } bind def
 /setcolorscreen { gsave setcolorscreen_orig grestore } bind def

How to concatenate strings? edit

PostScript doesn't have a build-in string concatenation operator. The following procedure, copied from GNU Ghostscript, seems to be the shortest.

 /concatstrings % (a) (b) -> (ab)  
   { exch dup length    
     2 index length add string    
     dup dup 4 2 roll copy length
     4 -1 roll putinterval
   } bind def  

Concatenation of multiple strings can be done more efficiently than calling concatstrings repeatedly. The strings are stored in array for the convenience of iteration.

 /concatstringarray  %  [(a) (b) ... (z)] --> (ab...z)  
    { 0 1 index { length add } forall string     
      0 3 2 roll      
        { 3 copy putinterval
          length add 
        }
      forall pop  
    } bind def

Where are min and max functions? edit

PostScript doesn't have built-in min and max operators but they can be easily coded as procedures.

 /min { 2 copy gt { exch } if pop } bind def
 /max { 2 copy lt { exch } if pop } bind def

Ghostscript has .min and .max operators in systemdict . For the backward compatibility Ghostscript also provides min and max procedures defined as:

 /max { .max } bind def
 /min { .min } bind def

How to sort an array? edit

Ghostscript has a bubble sort procedure in gs_init.ps.

 % <array> <lt-proc> .sort <array>
 /.sort 
   { 1 index length 1 sub -1 1 
       { 2 index exch 2 copy get 3 copy	% arr proc arr i arr[i] arr i arr[i]    
         0 1 3 index 1 sub 
           { 3 index 1 index get	        % arr proc arr i arr[i] arr imax amax j arr[j]      
             2 index 1 index 10 index exec
               {                               % ... amax < arr[j]	
                 4 2 roll      
               } 
             if pop pop    
           } 
         for             			% arr proc arr i arr[i] arr imax amax    
         4 -1 roll exch 4 1 roll put put  
       } 
     for
     pop
   } bind def

net.anastigmatix.Order provides insertion sort, quicksort, heapsort, array min, max, and simultaneous minmax, and arbitrary order statistics:

 /net.anastigmatix.Order /ProcSet findresource begin
 [7 49 73 58 30 72 44 78 23 9 40 65 92 42 87] //PolyCmp QuickSort

This Shell sort procedure sorts anything whose elements can be compared and exchanged by a procedure.

 %!
 % Shell sort in PostScript
 % Copyright (c) 2002 by Alex Cherepanov.  All rights reserved.
 % Distributed under GPL, http://www.gnu.org/licenses/gpl.txt
 
 %
 % Shell sort procedure based on compare and exchange operation
 % < i > < j > exch_less <bool> compares keys at positions i and j
 %                          exchange if not in order, retutn *i<*j
 % <len> is the number of elements
 %
 /shellsort                       % {} len -> -
   { dup dup 2 idiv               % {} len m p
       { dup 0 eq { exit } if
         exch                     % {} len p m
         15 le { dup 2 idiv } { dup } ifelse
         16#fffffffe and 1 add    % {} len p m'
         1 1 4 index 3 index sub  % {} len p m' 1 1 len-_m
           { 1 index neg 1        % {} len p m' is -m 1
               { 1 sub            % {} len p m' ii-1
                 2 copy add       % {} len p m' ii-1 m+ii-1
                 5 index exec
                   { exit
                   }
                 if
               }
             for
           }
         for
         exch 2 idiv              % {} len m' p'
       }
     loop
     pop pop pop pop              % -
   } bind def
 
 %
 % Sample unsorted array
 %
 /sample_array [ 1 8 76 3 7 0 7 8 55 86 5 58 57 55 3 6 9 6 66 4 3 4 8 65 8 8 55
                 4 5 88 55 3 6 7 44 5 7 4 7 43 3 ] def
 %
 % Sample array compare and exchange
 % The elements at positions i and j are compared and exchanged
 %
 % if (*i<*j)
 %   return true
 % (*i,*j) = (*j,*i)
 % return false
 %
 /array_exch_less        % i j -> bool
   { 6 index 3 1 roll    % [] i j  % get the element just below {exch}
     2 index exch        % [] i [] j
     4 copy              % [] i [] j [] i [] j
     get                 % [] i [] j [] i *j
     3 1 roll get        % [] i [] j *j *i
     2 copy ge           % [] i [] j *j *i *i<*j
       { pop pop pop pop pop pop //true
       }
       { exch            % [] i [] j *i *j
         4 1 roll        % [] i *j [] j *i
         put put //false
       }
     ifelse
   } bind def
 
 %
 % Sort the array
 %
 /array_sort  % [unsorted] -> [sorted]
   { //array_exch_less 1 index length shellsort
   } bind def
 
 %
 % Print the sorted array
 %
 sample_array array_sort ==

How can I display Copyright and other symbols? edit

From Level 2 on, the glyphshow operator has allowed a named glyph to be displayed:

% display a "registered trademark" symbol
/registered glyphshow

Where can I get more examples of PostScript code? edit

Books about PostScript include many simple PS programs.

The Ghostscript distribution has a few sample PostScript files in the examples directory. A large part of Ghostscript is implemented in PostScript language including a PDF 1.4 interpreter.

Adobe has published a few sample programs for Level 3 features.

Free sample library contains many good (and bad) PostScript files. The library collects interesting examples of PostScript, PDF, PCL, and TIFF files coded manually or harvested from applications.

For an understanding of typesetting procedures see 'Practical PostScript' A Beginner's Guide to Digital Typesetting, 90 pages (E-book 416k PDF). [[1]]

How to debug a PostScript program? edit

The first skill you should learn as soon as you can is how to interpret PostScript error messages. They are not always easy. Error reporting varies by product. Some products will not give PostScript error details (e.g. EPS import to Photoshop), and are best avoided for any learning purposes.

The standard PostScript error format is something like this

PS>0 1 2 3 4 5 put
%%[ Error: typecheck; OffendingCommand: put ]%%
PS><< >> image
%%[ Error: undefined; OffendingCommand: image ]%%

You will see this includes the error name, and a command causing the error. Please do not describe this as an "offending command" error, since all messages say that, and remember that both error name and offending command are important. The latter message means that a required key was not found in the image dictionary.

If you happen to be using Ghostscript, you may get more details. Observe that the error message includes the stacks, and the operator name.

GS>0 1 2 3 4 5 put
Error: /typecheck in --put--
Operand stack:   0   1   2   3   4   5
Execution  stack:   %interp_exit   .runexec2   --nostringval--    
--nostringval--   --nostringval--   2   %stopped_push   --nostringval--  
--nostringval--   %loop_continue   2   3   %oparray_pop   --nostringval--    
--nostringval--   false   1   %stopped_push   .runexec2   --nostringval--    
--nostringval--   --nostringval--   2   %stopped_push   --nostringval--   
--nostringval--   --nostringval--
Dictionary stack:   
--dict:1044/1123(ro)(G)--   --dict:0/20(G)--   --dict:69/200(L)--
Current allocation mode is local
Current file position is 16

You can look at the description of the operator, and the stack to see your operands, and often see why it is complaining. Then you can (sometimes) work out where in your original code the problem lies. Remember that a failed PostScript operator doesn't change the operand stack.

Ghostscript exits when an error happens in a file passed as a command line parameter. Use operator run to keep the session and examine operand stack interactively.

 $ gs
 GS> (foo.ps) run

Use the = and == commands to print out information about objects on the operand stack. To see the contents of a dictionary, push the dictionary on the stack and then use {== ==} forall. For example, to see the contents of the user dictionary, use userdict {== ==} forall.

Try to run the program on different interpreters. Different error messages may reveral more information about the problem. Ghostscript can print detailed dumps of operand and execution stacks when it runs with -dOSTACKPRINT and -dESTACKPRINT options respectively. The top element of the stack is printed last.

Error handler is a PostScript procedure that runs when PostScript interpreter encounters an error. It is initially installed by the PS interpreter but can be replaced by the job. The error handler provided by the PostScript driver is very basic - delete it. On Ghostscript you will get better error messages with the default error handler. On other interpreters you can use ehandler.ps provided by Adobe.

If the problem is not yet apparent try to make the smallest possible program that still has the problem by removing or commenting out pieces of code. Using { ... } pop construct is a convenient way to disable parts of PostScript code. Save every version of the file under a different name to have multi-level undo. When the file is reduced to a single procedure, try to replace it with inline code. When the procedure is buried in other code or redefined several times, try to load it at the execution spot and print. For instance: /foo load ==.

You can trace a PostScript program by adding print operators into procedures or redefining operators. The Ghostscript package includes a script traceop.ps which can help in putting a trace on operators. After including the script near the front of your postscript program, you put /foo traceop at the point where you want to start tracing all calls to operator foo. You then modify procedures /tracebefore and /traceafter to print some relevant diagnostics. For example, /tracebefore { count traceprint } def would print the whole stack just before entry into /foo. (/traceprint basically does a {print ==only } for as described above.) Operator /foo is then executed as normal. If a program doesn't render correctly on a raster device, chances are the same problem will occur during PS to PDF conversion. The PDF document preserves more information and can be interpreted as a trace of graphic operations.

LaserTalk was once part of the Adobe developer's kit. It was a visual front end to the PostScript printer. LaserTalk only traced the top level of execution.

PSAlter from Quite Software is the only visual PostScript debugger on the market.

How to include an EPS file? edit

EPS format is documented in Adobe technical note 5002, Encapsulated PostScript File Format Specification (PDF 0.2M) and 2nd edition of PostScript Language Reference Manual. The specification includes guidelines for creating EPS files (they are simply PostScript programs that contain a couple of required header comments and promise not to do certain things), and for importing EPS files. The EPS file text can simply be pasted into the enclosing PostScript program between a %%BeginDocument: and an %%EndDocument comment. (The %%BeginDocument: keyword can be followed by descriptive text such as the EPS file name.) It is the enclosing program's responsibility to establish a suitable state just before the inserted EPS and restore the prior state afterward. The program should:

  • take a state snapshot with save
  • redefine showpage as no-op
  • set the color space, color, line cap, line width, line join, miter limit, dash pattern, current path, overprint, and stroke adjust modes to specified defaults
  • present an empty operand stack and the default dictionary stack (but containing the no-op showpage)
  • compute and set a coordinate transformation that puts the EPS figure where it is wanted
  • set a clipping path matching the figure's bounding box

After the inserted EPS code, the enclosing program should discard anything the EPS code may have left on the operand and dictionary stacks, restore the prior contents, and then execute restore on the earlier save object, which will undo all of the other preparations.

Applications that output PostScript typically omit the code to do all of that at every place an EPS figure is inserted, and they often cut corners and omit code that makes simplifying assumptions. Especially when writing PostScript by hand, it can be more convenient to use, for example, the Anastigmatix StatEPSF, ReadyEPSF, ExecEPSF procedures, which automate the necessary steps. The following code is then all that's needed to place an EPS at (100,550), rotated 0 degrees and scaled by 1 in both axes:

 % in the document setup:
 /net.anastigmatix.Import /ProcSet findresource begin
 % at the point of import:
 { StatEPSF 100 550  0  1 1 ReadyEPSF ExecEPSF }
 currentfile exch exec
 %%BeginDocument: helloworld.eps
 ... the EPS file contents go here
 %%EndDocument

Of course, nothing stops an application from generating PostScript that way too.

Some EPS files contain preview images. In the DOS/Windows format, they are binary data that must be stripped out when pasting the EPS text into another program. The EPSI preview format is in the form of PostScript comments and can be removed to save space, but will not cause problems if left in place.

Does PostScript support unicode for CJK fonts? edit

PostScript does not specifically support Unicode. It includes general support (from level 2) for multi-byte (2, 3 or 4 byte) fonts. Unicode is just a special case of multi-byte encoding. There is no Unicode font as such, but you can use multi-byte CID fonts that provide support for ranges of Unicode.

There are no freely redistributable Unicode CMaps. They can be derived from MS Windows code pages and corresponding Adobe CMaps.

Developers often look for a "simple" way to just include Unicode strings with no checking for ranges, language etc. but this is a pipe dream.

Some PostScript engines also provide support for TrueType fonts that have no CID-mapping internally. In that case, no CID map is needed for these fonts, but only a read filter for decoding a Unicode-encoded stream for the string storing the byte sequences ; several decoding filters are possible, including those supporting UTF-8 and UTF-16, because the PostScript's "read" operator just expects the filter to return any convenient integer that is used as an index to the glyph in the font's dictionary.

Filters, that can be chained and used like other file objects by the read operator, are supported in PostScript Level 2. Note that most PostScript applications expect that bytesavailable is the number of integers that read can return without waiting or encountering an end-of-file (or end-of-string) condition.

The read operator is then not limited to returning integers in the range 0..255, so the actual return value from read is a code unit (or code points or glyph ID) in any convenient encoding that is supported as glyph indexes for the selected font, and the read operator will actually read as many bytes from its source (file, string or procedure) as needed by the decoding filter. Other standard filters support data decompression, or decoding hex or ASCII85 sequences from any source.

So instead of enumerating characters in a string using the forall operator, pass the string to a Unicode decoding filter, and use a read loop to enumerate characters (or glyph indexes) from the filter object, then render the characters using the returned integer index to lookup for glyphs in a composite font. If the PostScript engine does not handle a native support for Unicode or TrueType, you'll have to convert the TrueType font into a CID-mapped font and use a filter that will return CID values usable with the CID-mapped font loaded into the document preamble or transfered as a resource before your printed document.

You'll probably also need a layout engine (like Pango) to process the Unicode codepoints into series of glyph ids and precompute their position within the PostScript-rendered document where these will be encoded and decoded by the PostScript engine using the associated filter. Such text layout engine is needed anyway to support the BiDi alghorithm, as well as to render complex scripts, ligatures, contextual forms, or variants described in the font used in your document design...


Known errors

Known errors edit

This is a list of work-arounds for PostScript errors in proprietary software. Bugs in free software should be reported to the program maintainer and fixed. The fixes posted here try go to the root of the problem. This database of PostScript errors gives an insight into the user's perception of PostScript errors.

undefined in /RD edit

This problem can be caused by incorrect embedded Type 1 fonts in PDF files or PostScript files generated from PDF. Adobe Acrobat doesn't use procedures defined in Type 1 font and the problem may be left unnoticed.

Define the following procedures in userdict to work around the problem.

 /RD { string currentfile exch readstring pop } executeonly def
 /ND { noaccess def } executeonly def
 /NP { noaccess put } executeonly def

PageMaker 7.0 page information fails in level 1 mode edit

PageMaker 7.0 with Page Information printer's mark set ON generates incorrect PostScript file in level 1 mode. The file fails with invalidaccess in get or typecheck in get on any interpreter, regardless of the level.

The problem is caused by interaction between PageMaker code and Windows driver code. To print separations Adobe redefines a few operators, including setcolorspace and uses them even in level 1 mode. PostScript driver assumes that setcolorspace has no place in Level 1 PostScript and redefines it as {pop} as a precaution, erasing the earlier definition.

 /setcolorspace{!}b 

To fix the file this definition should be removed or commented out.


Using Ghostscript

Using Ghostscript edit

What is Ghostscript and where can I get it? edit

Ghostscript is a common open source software suite, which is based on an interpreter for Adobe Systems' page description language PostScript and their Portable Document Format (PDF). The suite is developed by Artifex Software and the worldwide community, it is mainly used for the rasterization and rendering of document pages to display or print them, and for the conversion between PostScript and PDF. It includes sets of free PostScript fonts and is used in many third party applications and GUIs.

Details and software downloads see Ghostscript.

How to create compressed CMYK TIFF? edit

Ghostscript have five TIFF devices for color management. And five TIFF compression devices, which produce only b/w images.

 gs -sDEVICE=tif32nc -sOutputFile=tiger.tiff -dEPSCrop examples/tiger.eps

What CJK fonts work on Ghostscript? edit

Unprotected CJK fonts work on Ghostscript just fine. It is not possible to install CSL (Adobe's CID Support Library) but most PostScript programs don't need it. CSL simulates OCF structures for the jobs that assume OCF fonts on the interpreter and manipulate them directly.

Heisei and KozMin CIDFonts are unprotected proprietary fonts developed by Adobe Systems. The installer that comes with the fonts runs on Mac and installs the fonts to a network printer using PAP protocol. To install the fonts on Ghostscript you need to copy CIDFont files to Resource/CIDFont/ directory.

The CIDFont resources are hidden in resource forks of invisible files in Mac file system. get-mac-cidfont extracts all CIDFont resources from the input file (normally /dev/cdrom) to a directory. The program also works on Windows NT.

How to avoid JPEG compression in PDF? edit

Ghostscript has overly aggressive heuristic identifying the images for JPEG compression. Using setdistillerparams operator one can manually select compression algorithm. Ghostscript accepts most distiller parameters (PDF 0.6M) as command line arguments in addition to setdistillerparams operator.

 ps2pdf -dAutoFilterColorImages#false -dColorImageFilter#/FlateEncode \
   -dAutoFilterGrayImages#false -dGrayImageFilter#/FlateEncode foo.ps foo.pdf

Ghostscript developers recognize this as a problem. The fix is expected real soon now.

Ghostscript fails with /invalidfont in findfont? edit

Most likely Ghostscript cannot access any fonts at all. To check what directories are searched for fonts, use

 gs -h

or

 gswin32c -h

How to create a semi-transparent object? edit

Adobe introduced semi-transparent objects in PDF 1.4. Many new RIP's (including Ghostscript) accept PDF 1.4 directly. So there is no need for the transparency features in PostScript.

  • Ghostscript supports PDF 1.4 in v. 8.00 and up
  • Adobe CPSI supports PDF 1.4 in v. 3015 and up

Standard PostScript has opaque color model. Newer objects completely obscure the objects underneath but parts of the new object can be excluded from painting by clipping path. On level 3 PostScript a sampled image can be used for clipping another sampled image. On level 2 a similar effect can be achieved by painting pattern color through the image mask.

Very limited transparency effects can be also achieved by overprinting spot colors and pure process colors.

PDF 1.4 interpreter in Ghostscript is implemented in extended PostScript language. The extensions are visible to the regular PostScript files and can be used to the same effect. The interface is partly documented in doc/language.htm. Read the source code for details.

PostScript output interferes with redirected device output. edit

PostScript files that write to stdout will interfere with device output to stdout. That is why since v.7.04 Ghostscript can assign the PostScript %stdout output to a file, leaving the actual stdout 'clean' for use as device output such as with -sOutputFile=- or -sOutputFile=%stdout

For instance, to discard PS %stdout output, such as from the '=' operator, when Ghostscript is being used as a filter the correct command line is:

 gs -q -sstdout=/dev/null -sOutputFile=- - | ...

With a little help from bash, named pipes can be used in place of regular files, avoiding all stdout-stderr problems.

 gs -sDEVICE=pswrite -o >(wc) -c showpage

How to fix a file generated by a pswrite device edit

Adobe PostScript interpreters and Ghostscript v. 8.55 and higher fail with /typecheck in --where-- on files with non-standard page sizes generated by old versions of Ghostscript with Subversion revisions 1225 to 2334. The affected code executes null where, which is not allowed by PostScript language.

The following IdiomSet resource can be installed on the PostScript interpreter to work around the problem. To activate the IdiomSet you need to copy it to /Resource/IdiomSet/ directory on the printer or host-based interpreter. The PostScript root directory on a host-based interpreter likely to be different from the system root. The file name doesn't matter but FixOldPSwrite is suggested. For a one-time replacement you can also prepend the file to your job file.

 %!
 % This IdionSet provides backward compatibility with the old pdfwrite.
 % pswrite device in Ghostscript 7.04 and older generated incorrect
 % PostScript code. It assumed that the null value can be looked up in
 % a dictionary. Adobe interpreters never accepted null as dictionary
 % key and Ghostscript doesn't do this since v. 8.55. (rev. 6956)
 %
 currentuserparams /IdiomRecognition get
 <</IdiomRecognition false>> setuserparams
 currentglobal true setglobal
 /FixOldPSwrite
 << /fix_old_pswrite
     [
       { PageSize aload pop
         3 index eq exch 4 index eq and
           { pop pop pop
           }
           { PageSize dup
             1 5 -1 roll put
             0 4 -1 roll put dup where
               { exch get exec
               }
               { pop /setpagedevice where
                   { pop 1 dict dup /PageSize PageSize put setpagedevice
                   }
                   { /setpage where
                       { pop PageSize aload pop
                         pageparams 3 { exch pop } repeat setpage
                       }
                     if
                   }
                 ifelse
               }
             ifelse
           }
         ifelse
       } bind
       { PageSize aload pop
         3 index eq exch 4 index eq and
           { pop pop pop
           }
           { PageSize dup
             1 5 -1 roll put
             0 4 -1 roll put dup //null eq { false } { dup where } ifelse
               { exch get exec
               }
               { pop /setpagedevice where
                   { pop 1 dict dup /PageSize PageSize put setpagedevice
                   }
                   { /setpage where
                       { pop PageSize aload pop
                         pageparams 3 { exch pop } repeat setpage
                       }
                     if
                   }
                 ifelse
               }
             ifelse
           }
         ifelse
       } bind
     ]
 >> /IdiomSet defineresource pop
 setglobal <</IdiomRecognition 3 -1 roll>> setuserparams

Ghostscript can not run my files edit

You try to learn postscript but you can not do:

 $ gs
 GS>(test.ps)run

stack dump from gs here ....

Current allocation mode is local
Last OS error: Permission denied
...
GS>

Since version 9.50 additional safety features are active. Now you need:

  $ gs -dNOSAFER