[comp.lang.postscript] Garden variety PS -> EPS filter

pvo@uther.CS.ORST.EDU (Paul V O'Neill) (07/12/89)

My boss is using FrameMaker 1.3b on a Sun-3/50 running SunOS 3.5.  She wants
to import some Postscript figures produced by a locally-written Postscript
plotting package.  Today she discovered that she can only import Encapsulated
Postscript.  

Does anyone have, or know of, code, packages, or applications that will 
convert garden-variety Postscript to Encapsulated Postscript?

Anything that runs on Suns, NeXT's, Mac's, AT's or RT's is applicable.

Thanks.  I will summarize.


Paul O'Neill                 pvo@oce.orst.edu
Coastal Imaging Lab
OSU--Oceanography
Corvallis, OR  97331         503-754-3251

bezanson@adobe.COM (Brian Bezanson) (07/13/89)

In article <11613@orstcs.CS.ORST.EDU> pvo@oce.orst.edu (Paul V O'Neill) writes:
>Does anyone have, or know of, code, packages, or applications that will 
>convert garden-variety Postscript to Encapsulated Postscript?
>
>Anything that runs on Suns, NeXT's, Mac's, AT's or RT's is applicable.
				     ^^^^^

According to the latest MacWeek (page 20), you can use Smart Art by Emerald
City Software to download the PostScript file to the printer, and it will
receive back an EPS image (complete with screen preview). You may need to
make some minor modifications, removing any showpages and making sure
a bounding box comment exists.

Hope that helps.

------------

Brian Bezanson					bezanson@adobe.com
Adobe Systems Inc.				AppleLink: D0124

cplai@daisy.UUCP (Chung-Pang Lai) (07/13/89)

In article <11613@orstcs.CS.ORST.EDU> pvo@oce.orst.edu (Paul V O'Neill) writes:
]My boss is using FrameMaker 1.3b on a Sun-3/50 running SunOS 3.5.  She wants
]to import some Postscript figures produced by a locally-written Postscript
]plotting package.  Today she discovered that she can only import Encapsulated
]Postscript.  
]

That is not true.  If she does not need WYSIWYG display, she can turn on the
printer code option of the textrect and import the PS program as text.
The printed page will show the PS graphics.  See P. 3-86 in Reference Manual.

The other way to do it is to put the following line in the printer code
textrect:
	#include "name-of-the-PS-program"
Make sure the line ends with a CR.

]Does anyone have, or know of, code, packages, or applications that will 
]convert garden-variety Postscript to Encapsulated Postscript?
]
]Anything that runs on Suns, NeXT's, Mac's, AT's or RT's is applicable.
]

I am also interested in a convertor from generic PS to Adobe Illustrator
format.  Since Adobe Illustrator generates very nice EPSF output for both
Mac and PC, you can get whatever you want from there.

I had some success converting a PS porgram into Adobe Illustrator format 
using sed.  It was a fluke though, the file did not use any fancy code.


-- 
.signature under construction ...
{pyramid, osu-cis, uunet, killer}!daisy!cplai    C.P. Lai
cplai%daisy.UUCP@uunet.UU.NET   cplai%daisy@killer.DALLAS.TX.USA
Daisy Systems Corp, 700B Middlefield Road, Mtn View CA 94039.  (415)960-6961

greid@adobe.com (Glenn Reid) (07/13/89)

In article <982@adobe.UUCP> bezanson@adobe.UUCP (Brian Bezanson) writes:
>In article <11613@orstcs.CS.ORST.EDU> pvo@oce.orst.edu (Paul V O'Neill) writes:
>>Does anyone have, or know of, code, packages, or applications that will 
>>convert garden-variety Postscript to Encapsulated Postscript?
>>
>>Anything that runs on Suns, NeXT's, Mac's, AT's or RT's is applicable.
>				     ^^^^^
>According to the latest MacWeek (page 20), you can use Smart Art by Emerald
>City Software to download the PostScript file to the printer, and it will
>receive back an EPS image (complete with screen preview). You may need to
>make some minor modifications, removing any showpages and making sure
>a bounding box comment exists.

Since you don't want the Macintosh preview, this won't help you.  Since
you need the PostScript code itself to be well-structured, this won't
help you.

Sometimes you can manually add some of the comments and other syntactic
sugar to the PostScript file to make it appear to be an Encapsulated
PostScript file, but EPSF really means more than that.  It means that
the program promises not to violate certain portability constraints,
and adding comments doesn't provide that.

One possibility (enclosed) is to use the Distillery to execute the
program and give you back a conforming PostScript file.  If the document
is only one page, the only difference between the conforming document
you get from the Distillery and a "true" EPSF file will be the first
line, which needs to look like this:

%!PS-Adobe-2.0 EPSF-2.0

(you add the EPSF-2.0 at the end).

Glenn Reid
Adobe Systems
Developer Tools & Strategies

------------------------ cut here -------------------------
%!PS-Adobe-2.1
%%Title: still.ps
%%Creator: Glenn Reid, Adobe Systems <adobe!greid@decwrl.dec.com>
%%CreationDate:	greid Wed Jul  6 18:02:53 1988 EDIT: Wed Jun  7 10:45:32 1989
%%VMUsage: 58008 (approx)
%%EndComments
 
% Notice: Copyright 1988 1989 Adobe Systems Incorporated.  All Rights Reserved.

/adobe_distill 155 200 add dict def	% 155 required by still.ps
/adobe_still_version ((V 1.0d release 11 edit 4)) def

% options:
/debug true def			% generate debugging messages
/messages false def		% generate more debugging messages (verbose!)
/trace true  def		% print tracing messages like "page: 3"
/substitutefonts true def	% substitute fonts if guess_font fails....
/includeuserfonts true def	% copy embedded user-defined fonts to output?
/printpages false def		% do you want the pages to print?
/optimize true  def		% optimize "show" to "widthshow", etc.
/tolerance .05 def		% for "essentially equal to" operations
/cachefonts true def		% use the /F1 <font> def cache technique
/cachedir 60 dict def		% how many font dicts to cache (optimization)
/includeprologue true def	% output files with/without prologue
/usernametrack 500 def		% how many names to track in user-defined fonts
				% (uses much VM; decrease if no user fonts)
/hexformat 78 def		% width of column for formatted hex data

% 
% HOW TO USE: [see section below]
%
% OVERVIEW:
%	This is a meta-utility program that "distills" any PostScript
%	language program into a simpler one.  The resulting program
%	will print exactly the same page as the original, but all
%	unnecessary execution overhead is eliminated and the file is
%	clean, uniform, and fast.
%
% RELEASE NOTES: [recent changes and details]
%	First public release: 2/10/89
%	Second release (numbered release 8): 2/17/89
%	    - reimplemented guess_font routines
%	    - added support for color; not careful about RGB->CMYK->RGB
%	    - added selective printing of pages during distill
%	Release 9: 3/2/89
%	    - fixed color-induced [major efficiency loss] bug
%	    - produces %%BoundingBox and %%PageBoundingBox info (atend)
%	    - works better (bugs fixed) on rotated (landscape) documents
%	    - fixed horrible bug related to CTM that made it resolution-
%	      dependent in some cases.
%	    - included flag to omit the prologue on output if desired
%	    - moved some of the flags to the beginning of the file
%	    - improved prologue code to simulate CMYK color with RGB
%	Release 10: 3/10/89
%	    - fixed bug related to rotated text
%	    - fixed rotated charpath bug mentioned in KNOWN PROBLEMS list
%	    - fixed bug with "closepath" followed by "rmoveto"
%	    - '=' and 'print' operators now pass data through to output
%	    - bug fixes for and much better support of user-defined fonts
%	    - (edit 07) fixed "undefined" "fd" problem.
%	    - (edit 08) took out redefinitions of '=' and 'print'; fixed
%	      a different "undefined" "fd" problem!
%	Release 11: 6/7/89
%	    - release numbered (V 1.0d release 11 edit 4)
%	    - most reported bugs fixed
%	    - optimization added for vertical and horizontal lines
%	    - code from Anders Blomdell for arrayeq and formatted hex output
%	    - fixed (I think) problems with dropped lines in MacDraw files
%	    - declared "Towneley Plays" test file to be incorrigible
%	    - adjusted ProcSet comments
%	    - fixed bug that generated extra blank pages at end of doc.
%
% MANY USES:
%	* If you archive documents in PostScript format, they can often
%	  be made more compact and efficient by distilling them.
%	* As a development tool, you can see what your program is
%	  really doing, and how simple and fast the driver could be.
%	* Distilled files can be used as an interchange format,
%	  since arbitrary PostScript files can be converted to this
%	  uniform representation.
%	* If your program can parse distilled files, then any arbitrary
%	  PostScript program can be used as input after distilling.
%	* Many others.
%
% FEATURES:
%	* correctly distills arbitrarily complex PostScript programs
%	* output is universal, simple, and in default user coordinates
%	* handles "charpath", "image", "imagemask", "awidthshow", etc.
%	* correctly follows "save", "restore", "gsave", "grestore"
%	* re-encodes fonts automatically to match application encoding
%	* reduces prologue size to only about 25-30 lines
%	* For machine-generated code:
%	    * output files are almost always SMALLER than original files
% 	    * output files are almost always FASTER than original files
%	* optimizes "show" to use "widthshow" whenever possible.
%	* uses save/restore at page boundaries
%	* observes structuring conventions and page independence
%	* caches font dictionaries instead of repeating "findfonts"
%	* output is normally VERY fast.
%
% HOW TO USE:
%	This program redefines a bunch of operators, and is invoked
%	with the word "distill".  This file has to precede the job it is
%	distilling, and you have to invoke it by calling "distill".
%
%	PRINTERS:
%	    In general, start with this file (still.ps), add the word
%	    "distill" at the end (to invoke the procedure), and tack
%	    any PostScript language file onto the end.  Send this to
%	    your favorite PostScript printer with an appropriate
%	    end-of-file indication at the end.  Results will
%	    be returned across communication channel, often to a log
%	    file somewhere (Unix: /usr/adm/printername.log)
%
%	INTERPRETERS: if you have an interpreter with a file system
%	    handy, first type "(still.ps) run" to load this file, then
%	    distill your file like this: "(prog.ps) distill".  It will
%	    write the results in "prog.psx" (appends an x to the file
%	    name you give it).
% 
%	MACINTOSH: I have written a small Mac utility that is called
%	    "DistillPS" (an adaptation of "SendPS") that will perform the
%	    above PRINTER steps for you.  If you are an Adobe registered
%	    developer, you can get a copy directly from Adobe (or see
%	    posting in USENET comp.binaries.mac group).
%
% BACKGROUND
% The basic idea is to execute the input file completely, with all of
% the painting operators redefined.  When one of these operators is
% called by the client program, the distillery will write the
% path the output file (with all coordinates normalized to the default
% userspace coordinate system).  Note that it will usually take LONGER
% to distill a file than it would to print it, because it executes the
% whole program, and much of it in a redefined state (slower).  Usually
% only about 20% slower than original print time to distill.
% 
% The routines in this file are broken down into several areas.  Most
% of them are concerned with writing things to the output file,
% actually, although there are two other interesting areas.  The first
% are the graphics state procedures, which attempt to keep track of the
% graphics state and, when a painting op is called, it writes out any
% changes to the graphics state since the last time it was called.  This
% keeps each painting op from having to write gstate itself.  The other
% interesting procs are simply the redefinitions of the painting ops
% themselves.
%
% KNOWN COMPATIBLE PROGRAMS
% The following applications have been tested (with some version of the
% driver, at least), successfully:
%	Lotus Manuscript
%	Macintosh "LaserPrep" (all documents, I think)
%	DEC's VaxDocument
%	Scribe
%	PageMaker
%	Frame Maker
%	Adobe Illustrator
%	TranScript (ditroff and enscript drivers)
%	Pedigree Plot package (incomplete testing)
%
% KNOWN PROBLEMS:
%	Clipping isn't handled correctly.
%
%	The bounding box for text is a crude estimate.
%
%	Some font tricks are difficult or impossible to distill correctly.
%	Especially those that involve sharing various parts of a font
%	between different font dictionaries, or changing the contents
%	of a font after "definefont" has been executed.  Luckily there
%	aren't many programs that do things like that.
%
%	Hand-written PostScript language programs (especially those
%	that take advantage of looping constructs) may get BIGGER
%	when you distill them, because the Distillery unrolls all loops.
%	It is really intended for machine-generated files, but it should
%	still work on programs tightly coded by hand (like Cookbook
%	examples).
%
%	Use of the "put" and "putinterval" operators to overwrite
%	string bodies can confuse the optimization technique.  If you
%	see strange output (wrong characters printed, especially),
%	try changing "/optimize true def" to "/optimize false def"
%	at the very beginning of this program.
%
%	Programs that use the "transform" operator to make resolution-
%	rounding decisions may have the output file bound to a specific
%	resolution.  The last ProcSet (called "hacks") redefines a few
%	operators to try to work around this.  Output file is still
%	device-independent in any case, but might look different.
%
%	Distillery relies on bug in save/restore related to string bodies
%	to preserve some information across save/restore. It is localized
%	to the "adobe_staticvar" procedure set, but may not always work.
%
%	In order to optimize re-encoding of fonts, the distillery takes
%	an educated guess that the first re-encoded font it sees will
%	have a representative encoding vector ("stdvec").  If this
%	first font is not encountered before other marks are made, the encoding
%	vector cannot be produced in the %%BeginSetup section, and the still
%	is forced to repeat the vector every time a font is used.  Work
%	is in progress on a heuristic to improve this.
%
%       In order to avoid building up the dictionary stack during
%       execution, all definitions are made in one dictionary
%       (PROLOGUE) and it is not explicitly brought to the top of
%       the dictionary stack for each operation (to avoid
%       "dictstackoverflow" errors).  Most of the identifiers have
%       been chosen to be reasonably unique, but there could be a
%       conflict if user programs use the same names.
%
%	Sometimes generates unnecessarily verbose code in the presence
%	of lots of save/restores in original file.  Try distilling the
%	output a second time to improve this (like whiskey)....
%
%	Some of the ProcSets depend on each other in weird ways, which
%	is wrong, since only the script should depend on the procset
%	definitions.  Eventually this will get fixed.
%
%	Does not always work correctly with user-defined fonts, especially
%	those defined by the standard TeX driver (unfortunately).  In
%	particular, TeX bitmap fonts that are defined and have characters
%	added on the fly are almost impossible to deal with reliably in this
%	distillery approach.

%%BeginProcSet: originals 0.5 0
% This dictionary contains the original definitions of native operators
% that have been redefined by the Distillery.  They are needed on
% occasion to permit the original program to execute operators without
% having the results distilled.  The motivating factor for this is
% user-defined fonts, which "draw" into the font cache, but the effects
% are not wanted in the output file.
%
% This also serves as a list of the redbook operators that are redefined
% by the distillery code.

mark
  /show
  /widthshow
  /ashow
  /awidthshow
  /kshow
  /fill
  /eofill
  /stroke
  /clip
  /image
  /imagemask
  /showpage
  /pathbbox
  /save
  /restore
  /gsave
  /grestore
  /charpath
  /newpath
  /definefont
  /flushfile
  /=
  /print
counttomark dup dict begin { dup load def } repeat pop
/originals currentdict end def

%%EndProcSet: originals 0.5 0

%%BeginProcSet: distill_defs 1.0 0
/setpacking where { pop currentpacking true setpacking } if
/firstmtx matrix currentmatrix def

/bdef { bind def } bind def

/ifnotdef { %def
  % only does the "def" if the key has not already been defined:
    1 index where { pop pop pop }{ def } ifelse
} bdef

/*flushfile /flushfile load ifnotdef

printpages not { %if
    /showpage { erasepage initgraphics } bind def
} if

/currentcmykcolor where { pop }{ %else
    /currentcmykcolor { %def
        currentrgbcolor 3 { 1 exch sub 3 1 roll } repeat 0
    } bind def
} ifelse

/setpacking where { pop setpacking } if
%%EndProcSet distill_defs 1.0 0

%%BeginProcSet: Adobe_staticvar 1.0 0
    % this procedure set implements the "magic" stuff to hide numbers
    % and other things where they will not be subject to save/restore
    /magicval { 8 string } bdef
    /hideval { %def	% /name int :	% "hideval" uses save/restore bug!
	exch load dup 0 (\040\040\040\040\040\040\040\040) putinterval
	exch (\040\040\040\040\040\040\040\040) cvs
	dup length 8 exch sub exch putinterval
    } bdef
    /magicbool { 5 string } bdef
    /hidebool { %def	% /name int :	% "hideval" uses save/restore bug!
	exch load dup 0 (\040\040\040\040\040) putinterval
	exch (\040\040\040\040\040) cvs 0 exch putinterval
    } bdef
    /cvnum { cvx exec } bdef	% makes hidden val back into an integer
    /cvbool { cvx exec } bdef	% makes hidden val back into a boolean
    /hidefontname { %def
	% hides a font name in a string body, for use in %%DocumentFonts
	scratch cvs
	% look to see if it is already in the docfonts string:
	% lots of hacks to search for (FontName\n), not just (FontName)
	save	% cause we're using memory for temporary string
	    adobe_distill begin
		1 index length 1 add string /tmpstring exch def
		tmpstring dup length 1 sub (\040) 0 get put
		tmpstring 0 3 index putinterval
		pagefonts tmpstring search {pop pop pop false}{pop true} ifelse
		docfonts tmpstring search {pop pop pop false}{pop true}ifelse
	    end
	3 -1 roll restore		% roll save object past booleans

	% first deal with docfonts, then with pagefonts booleans
	{ %ifelse
	    exch	% extra boolean for page fonts
	    dup dfontcount cvnum 1 index length add 1 add
	    docfonts length lt {
		dup docfonts exch dfontcount cvnum exch putinterval
		length 1 add dfontcount cvnum add /dfontcount exch hideval
		docfonts dfontcount cvnum 1 sub (\040) putinterval
	    }{ %else
		pop (% No more room for fonts in document font list\n) d=
	    } ifelse
	    messages { %if
		(document fonts: ) pr=
		docfonts 0 dfontcount cvnum getinterval d= flush
	    } if
	    exch % page font boolean still on stack, under "dup"ed string
	}{ } ifelse
	{ %ifelse
	    pfontcount cvnum 1 index length add 1 add
	    pagefonts length lt {
		dup pagefonts exch pfontcount cvnum exch putinterval
		length 1 add pfontcount cvnum add /pfontcount exch hideval
		pagefonts pfontcount cvnum 1 sub (\040) putinterval
	    }{ %else
		pop (% No more room for fonts in page font list\n) d=
	    } ifelse
	    messages { %if
		(page fonts: ) pr=
		pagefonts 0 pfontcount cvnum getinterval d= flush
	    } if
	}{ pop } ifelse
    } bdef
%%EndProcSet: Adobe_staticvar 1.0 0

%%BeginProcSet: distill 1.0 0
/setpacking where { pop currentpacking true setpacking } if

/adobe_distill dup where { pop pop }{ 165 200 add dict def } ifelse

% some variables
    % magic variables depending on "hideval", not subject to save/restore
    /pagecount magicval def	/pagecount 1 hideval
    /beginsetup magicbool def	/beginsetup true hidebool
    /lastshowpage magicbool def	/lastshowpage false hidebool
    /begunpage magicbool def	/begunpage false hidebool
    /?distilling magicbool def	/?distilling true hidebool

    /dfontcount magicval def 	/dfontcount 0 hideval
    /pfontcount magicval def	/pfontcount 0 hideval
    /docfonts 40 30 mul string def	    % room for 40 30-byte font names
    /pagefonts 40 30 mul string def	    % room for 40 30-byte font names
    /LLx magicval def		/LLx 10000 hideval
    /LLy magicval def		/LLy 10000 hideval
    /URx magicval def		/URx -10000 hideval
    /URy magicval def		/URy -10000 hideval
    /docLLx magicval def	/docLLx 10000 hideval
    /docLLy magicval def	/docLLy 10000 hideval
    /docURx magicval def	/docURx -10000 hideval
    /docURy magicval def	/docURy -10000 hideval

    /optim optimize def
    /scratch 128 string def
    /fontcount 0 def
    /indentlevel 0 def
    /ANYtype null def
    /insideproc false def
    /Dfont null def
    /Ffont null def
    /Fname null def
    /lastshow false def
    /imageproc null def
    /imagematrix null def
    /imagedepth null def
    /imageheight null def
    /imagewidth null def
    /unames usernametrack dict def  % for keeping track of user-defined names

% a few of them go into userdict:
/cvp {
    messages { % ifelse
	(                     ) cvs pr= (\040) pr=
    }{ pop } ifelse
} bdef
/pr= { messages { rprint }{ pop } ifelse } bdef
/d= { messages { r= }{ pop } ifelse } bdef

/distill {
    adobe_distill begin
	debug{(%!PS-Adobe-2.1 debug version ) rprint adobe_still_version == }if
	userdict /orig_dictcount countdictstack put
	count 0 eq { %ifelse
	    /INfile (%stdin) def
	    /OUTfile (%stdout) def
	    /fd (%stdout) (w) file def
	    initstill
	    writeprologue
	    initgstate
	    INfile (r) file cvx exec
	    writetrailer
	}{ %else
	    dup type /stringtype ne { %if
		(\n% Distill Error; invoked with bogus file name: ) print
		== (\n) print flush
		stop
	    } if
	    /filenameforall where { pop }{ %ifelse
		(\n% Distill Error; invoked with file name: ) print == 
		(% This interpreter cannot open files directly.) = 
		(% Please add "distill" at end of file and concatenate with) = 
		(% file to be distilled.) = (\n) print flush
		stop
	    } ifelse
	    initgraphics
	    /saveall save def
		/INfile exch def
		/OUTfile INfile length 1 add string def
		OUTfile 0 INfile putinterval
		OUTfile dup length 1 sub (x) 0 get put
		trace { (output file: ) rprint OUTfile == } if
		/outfile OUTfile (w) file def
		/fd /outfile load def
		initstill
		writeprologue
		initgstate
		debug { %ifelse
		    INfile run
		}{ % else
		    { INfile run } stopped { % if
			 errordict begin $error begin
			    (\n%%[Error: ) wout
			    /errorname load =string cvs wout
			    (; OffendingCommand: ) wout
			    /command load =string cvs wout (]%%) wout writeNL
			    (STACK:) writeop /ostack load type /arraytype eq {
				ostack { =string cvs writeop } forall
			    } if
			    fd systemdict /flushfile get exec
			    handleerror
			end end
		    } if
		} ifelse
		writetrailer
		fd closefile
		countdictstack orig_dictcount sub { end } repeat
		clear
	    saveall { restore } stopped { %if
		trace { (couldn't restore after distill.) r= } if
	    } if
	} ifelse
   end
} bdef

% the rest of them go in "adobe_distill"
adobe_distill begin
    /setdistill { %def
	/?distilling exch hidebool
    } bdef

    /initstill { %def
	/beginsetup true hidebool
	/lastshowpage false hidebool
	/begunpage false hidebool
	/pagecount 1 hideval
	/STDvec 0 hideval
	/PAGEvec 0 hideval
	/dfontcount 0 hideval
	/pfontcount 0 hideval
	/LLx 10000 hideval  /LLy 10000 hideval
	/URx -10000 hideval /URy -10000 hideval
	/docLLx 10000 hideval  /docLLy 10000 hideval
	/docURx -10000 hideval /docURy -10000 hideval
	/SharedFontDirectory where { %ifelse
	    /SharedFontDirectory get
	}{ /FontDirectory load } ifelse
	/FontDirectory exch def
	0 1 pagefonts length 1 sub { pagefonts exch 0 put } for
	0 1 docfonts length 1 sub { docfonts exch 0 put } for
    } bdef
    debug { %if
	/BB {
	    debug {
		(% BBox: ) pr=
		LLx pr= ( ) pr= LLy pr= ( ) pr=
		URx pr= ( ) pr= URy pr= (\n) pr= flush
		(% DocBBox: ) pr=
		docLLx pr= ( ) pr= docLLy pr= ( ) pr=
		docURx pr= ( ) pr= docURy pr= () r= flush
	    } if
	} bdef
    } if
    /?box { %def	% X Y
	dup URy cvnum gt { dup /URy exch cvi hideval } if
	dup LLy cvnum lt { dup /LLy exch cvi hideval } if pop
	dup URx cvnum gt { dup /URx exch cvi hideval } if
	dup LLx cvnum lt { dup /LLx exch cvi hideval } if pop
    } bdef
    /doc?box {
	dup docURy cvnum gt { dup /docURy exch cvi hideval } if
	dup docLLy cvnum lt { dup /docLLy exch cvi hideval } if pop
	dup docURx cvnum gt { dup /docURx exch cvi hideval } if
	dup docLLx cvnum lt { dup /docLLx exch cvi hideval } if pop
    } bdef
    /pageBBox-docBBox {
	LLx cvnum LLy cvnum doc?box
	URx cvnum URy cvnum doc?box
    } bdef
    /writeRmove { %def
	2 copy lineY sub exch lineX sub exch
	dup 0.0 eq { pop writenum (x) writeop }{ %ifelse
	    1 index 0.0 eq { writenum (y) writeop pop }{ %ifelse
		writepair (r) writeop
	    } ifelse
	} ifelse
	2 copy ?box
	/lineY exch store /lineX exch store
    } bdef
    /writelines { %def
	counttomark REPEAT_LINETO_THRESHOLD gt { % ifelse
	    counttomark /lcount exch store
	    lcount -2 2 { %for
		dup /rcount exch store
		-2 roll 2 copy lineY sub exch lineX sub exch 4 -2 roll
		2 copy ?box
		/lineY exch store /lineX exch store
		rcount 2 roll
	    } for
	    lcount 2 idiv { writepair writeNL } repeat
	    lcount 2 idiv writenum (R) writeop
	}{ % else
	    counttomark -2 2 { -2 roll writeRmove } for
	} ifelse
    } bdef
    /writepath {
	/closed false store
	% optimize special case of just "moveto lineto stroke"
	mark
	% pathforall
	{ counttomark 2 gt { cleartomark false exit } if thruCTM true }
	{ counttomark 5 gt { cleartomark false exit } if thruCTM true }
	{ cleartomark false exit }
	{ cleartomark false exit }
	pathforall { %ifelse
	    counttomark 5 ne { %ifelse
		% degenerate case...
		ischarpath counttomark 2 eq and {	% just moveto
		    2 copy ?box
		    writepair (m) writeop
		} if
		cleartomark
	    }{ %else
		3 -1 roll pop
		/?simplepath true store
		simplepath astore pop
		pop %mark
	    } ifelse
	}{ %else
	    /?simplepath false store
	    mark
	    { % moveto
		closed { (cp ) wout /closed false store } if
		counttomark 2 gt { %if
		    counttomark 1 add 2 roll writelines 3 1 roll
		} if
		2 copy thruCTM /lineY exch store /lineX exch store
		/closeX lineX store  /closeY lineY store
		2 copy ?box
		writeTpair (m) writeop
	    } % moveto proc
	    { %lineto proc
		thruCTM count 490 gt { writelines } if
	    } % lineto
	    { % curveto
		counttomark 6 gt { %if
		    counttomark 1 add 6 roll writelines 7 1 roll
		} if
		2 copy thruCTM /lineY exch store /lineX exch store
		3 { %repeat
		    6 -2 roll 2 copy thruCTM
		    2 copy ?box
		    exch writenum writenum
		} repeat (c) writeop 6 {pop} repeat
	    } % curveto
	    { % closepath
		counttomark 0 gt { writelines } if
		/closed true store
		/lineX closeX store  /lineY closeY store
	    } % closepath
	    pathforall
	    counttomark 0 gt { writelines } if
	    pop %mark
	} ifelse
    } bdef
    /hashpath { %def
      % manufacture a [fairly] unique integer to represent a path:
	-1				% initial value
	{ .5 add add 2 div add }	% moveto
	{ add sub }			% lineto
	{ add add sub add add add }	% curveto
	{ 1 add }			% closepath
	pathforall
	dup 100 lt { 10 mul truncate 10 div } if
    } bdef
    /hashencoding { %def
      % manufacture a [fairly] unique integer for an encoding vector,
      % by alternately adding then subtracting the length of the name.
      % The alternation makes reordered lists with same names still come out
      % with a different hash value (the "-1 exch" and the "mul" do this)
	-1 exch 0 exch			% initial value: 0
	{ % forall
	    dup type /nametype eq { length }{ pop 1 } ifelse
	    2 index mul add	% multiply by 1 or -1 and add
	    exch -1 mul exch	% flip 1 and -1
	} forall
	exch pop			% get rid of -1, leave hash val
    } bdef
    /STDvec magicval def /STDvec 0 hideval
    /PAGEvec magicval def /PAGEvec 0 hideval
    /enc1 null def /enc2 null def
    /diffencoding { %def
	% check the "top128" boolean to see if it's worth reencoding them
	/enc2 exch store /enc1 exch store	% enc2 is the new one
	[ 
	    32 1 127 { %for				% 0 1 255 ??
		dup dup enc2 exch get exch enc1 exch get
		1 index eq { pop pop } if
	    } for
	]
    } bdef
    /indent { indentlevel { fd (  ) writestring } repeat } bdef
    /++ { dup load 1 add store } bdef
    /-- { dup load dup 1 ge { 1 sub } if store } bdef

end %adobe_distill
/setpacking where { pop setpacking } if
%%EndProcSet distill 1.0 0

%%BeginProcSet: distill_writetofile 1.0 0
/setpacking where { pop currentpacking true setpacking } if
/adobe_distill dup where { pop pop }{ 165 200 add dict def } ifelse
adobe_distill begin
    /writetrailer { %def	% :
	stackptr 0 ne { stackshow } if
	begunpage cvbool { %if
	    lastshowpage cvbool not { %if
		( /showpage {} def) writeop
	    } if
	    pagecount cvnum scratch cvs wout ( ENDPAGE\n) wout
	    (%%PageTrailer) writeop
	    (%%PageFonts: ) wout
	    pfontcount cvnum 0 eq { writeNL }{ %else
		pfontcount cvnum 200 lt { %ifelse
		    pagefonts 0 pfontcount cvnum getinterval writeop
		}{ %else
		    pagefonts (\040) search not { writeop }{ %else
			writeop	% first one without the %%+
			{ %loop
			    search { (%%+ ) wout writeop }{ %else
				(\000) search { writeop pop pop }{ pop } ifelse
				exit
			    } ifelse
			} loop
		    } ifelse
		} ifelse
		0 1 pfontcount cvnum { pagefonts exch 0 put } for
		/pfontcount 0 hideval
	    } ifelse
	    LLx 10000 eq LLy 10000 eq or
	    URx -10000 eq URy -10000 eq or or not {
		(%%PageBoundingBox: ) wout
		  LLx cvnum writenum LLy cvnum writenum
		  URx cvnum writenum URy cvnum writenum writeNL
	    } if
	    pageBBox-docBBox
	} if
	(%%Trailer) writeop
	(end %PROLOGUE) writeop
	(%%Pages: ) wout pagecount cvnum writenum writeNL
	(%%BoundingBox: ) wout
	  docLLx cvnum writenum docLLy cvnum writenum
	  docURx cvnum writenum docURy cvnum writenum writeNL
	(%%DocumentFonts: ) wout
	dfontcount cvnum 0 eq { writeNL }{ %else
	    dfontcount cvnum 200 lt { %ifelse
		docfonts 0 dfontcount cvnum getinterval writeop
	    }{ %else
		docfonts (\040) search not { writeop }{ %else
		    writeop	% first one without the %%+
		    { %loop
			search { (%%+ ) wout writeop }{ %else
			    (\000) search { writeop pop pop }{ pop } ifelse
			    exit
			} ifelse
		    } loop
		} ifelse
	    } ifelse
	} ifelse
	(%%EOF) writeop
    } bdef
    /writecomments { %def
	fd (%!PS-Adobe-2.1\n) writestring
	fd (%%Title: ) writestring fd OUTfile writestring fd (\n) writestring
	fd (%%Creator: Glenn Reid and still.ps ) writestring
	fd adobe_still_version writestring fd (\n) writestring
	fd (%%BoundingBox: (atend)\n) writestring
	fd (%%Pages: (atend)\n) writestring
	includeprologue { %ifelse
	    fd (%%DocumentProcSets: Adobe_distill 0.112\n) writestring
	}{ %else
	    fd (%%DocumentNeededProcSets: Adobe_distill 0.112\n) writestring
	} ifelse
	fd (%%EndComments\n) writestring
    } bdef
    /writeprologue { %def	% :
	writecomments
	includeprologue { %ifelse
	    mark
	    (%%BeginProcSet: Adobe_distill 0.112 0)
	    (/PROLOGUE 30 40 add dict def)
	    ( % 30 procedure entries + room for 40 cached font dictionaries)
	    ( PROLOGUE begin)
	    ( /clip { } def    % causes problems. remove if "clip" is needed)
	    ( /bdef { bind def } bind def	/ldef { load def } bdef)
	    ( /T { moveto show } bdef	/A { moveto ashow } bdef)
	    ( /W { moveto widthshow } bdef	/AW { moveto awidthshow } bdef)
	    ( /f /fill ldef			/R { { rlineto } repeat } bdef)
	    ( /r /rlineto ldef		/L { { lineto } repeat } bdef)
	    ( /m /moveto ldef		/l { moveto lineto stroke } bdef)
	    ( /x { 0 rlineto } bdef		/y { 0 exch rlineto } bdef)
	    ( /X { moveto 0 rlineto stroke } bdef)
	    ( /Y { moveto 0 exch rlineto stroke } bdef)
	    ( /c /curveto ldef		/cp /closepath ldef)
	    ( /s /stroke ldef		/w /setlinewidth ldef)
	    ( /g /setgray ldef		/j /setlinejoin ldef)
	    ( /d /setdash ldef		/F /setfont ldef)
	    ( /C /setcmykcolor where { /setcmykcolor get }{ %ifelse)
	    (   { %def)
	    (     1 sub 3 { 3 index add neg dup 0 lt { pop 0 } if 3 1 roll } repeat)
	    (     setrgbcolor)
	    (   } bind)
	    ( } ifelse def)
	    ( /selectfont where { pop }{ %ifelse)
	    (     /selectfont { exch findfont exch scalefont setfont } bdef)
	    ( } ifelse)
	    ( /MF { exch findfont exch makefont setfont } bdef)
	    ( /FF /selectfont ldef)
	    ( /DF { selectfont currentfont def } bdef)
	    ( /BEGINPAGE { pop /pagesave save def } bdef)
	    ( /ENDPAGE { pop pagesave restore showpage } def)
	    ( /REMAP { %def)
	    (   FontDirectory 2 index known { pop pop pop } { %ifelse)
	    (     findfont dup length dict begin)
	    (       { 1 index /FID ne {def}{pop pop} ifelse } forall)
	    (       exch dup length 0 gt { /Encoding exch def }{ pop } ifelse)
	    (     currentdict end definefont pop)
	    (   } ifelse)
	    ( } bdef)
	    ( /RECODE { %def)
	    (    3 -1 roll 1 index findfont /Encoding get 256 array copy exch)
	    (    0 exch { %forall)
	    (     dup type/nametype eq)
	    (       { 3 {2 index} repeat put pop 1 add }{ exch pop }ifelse)
	    (    } forall pop 3 1 roll REMAP)
	    ( } bdef)
	    ( end %PROLOGUE)
	    (%%EndProcSet: Adobe_distill 0.112 0)
	    % write all the above strings to the output file:
	    counttomark -1 1 { %for
		-1 roll fd exch writestring fd (\n) writestring
	    } for
	    fd systemdict /flushfile get exec
	    pop %mark
	}{ %else
	    (%%IncludeProcSet: Adobe_distill 0.112 0\n) fd exch writestring
	} ifelse
	fd (%%EndProlog\n) writestring
	fd (%%BeginSetup\n) writestring
	fd (PROLOGUE begin\n) writestring
    } bdef
    /checksetup { %def
	% called from "fontstate", "graphicstate", and "definefont"
	beginsetup cvbool {
	    /beginsetup false hidebool
	    fd (\n%%EndSetup\n%%Page: 1 1\n) writestring
	    fd (%%PageFonts: (atend)\n) writestring
	    fd (%%PageBoundingBox: (atend)\n) writestring
	    fd (1 BEGINPAGE\n) writestring
	    /begunpage true hidebool
	    /fontcount 0 store
	}{ %else
	    lastshowpage cvbool { %if
		/lastshowpage false hidebool
		/fontcount 0 store
		writeNL (%%Page: ) wout
		trace { (page: ) rprint pagecount cvnum == flush } if
		/pagecount pagecount cvnum 1 add hideval
		pagecount cvnum dup writenum writenum writeNL
		(%%PageFonts: (atend)) writeop
		(%%PageBoundingBox: (atend)) writeop
		pagecount cvnum scratch cvs wout ( BEGINPAGE\n) wout
		/begunpage true hidebool
	     % invalidate all remapped fonts, for page independence
		FontDirectory { %forall
		    exch pop dup /FontInfo known { %ifelse
			/FontInfo get dup /pleasemap known { %ifelse
			    begin (Glenn Reid)
				pleasemap cvbool not {
				    /pleasemap true hidebool
				} if pop
			    end
			}{ pop } ifelse
		    }{ pop } ifelse
		} forall
		currentfont null ne { % if
		    currentfont dup /FontInfo known { %ifelse
			/FontInfo get dup /pleasemap known { %ifelse
			    begin /pleasemap true hidebool end
			}{ pop } ifelse
		    }{ pop } ifelse
		} if
		% forcegstate
	    } if
	} ifelse
    } bdef
    /writenamearray {		% [ /name ... ] :
	fd ([) writestring
	/indentlevel ++ fd (\n) writestring indent
	/CNT 1 store
	%| maintain CNT to count bytes.  wrap lines at a reasonable
	%| place when writing out character names, to avoid long lines
	{ %forall
	    fd (/) writestring
	    dup type /nametype eq { scratch cvs }{ pop (.notdef) } ifelse
	    dup  length 1 add CNT add /CNT exch store  fd exch writestring
	    CNT 60 ge { /CNT 1 store fd (\n) writestring indent } if
	} forall
	/indentlevel -- fd (\n) writestring indent fd (]) writestring
    } bdef
    /writediffencoding {	% [ 32/name 37/etc ... ] :
	fd ([) writestring
	/indentlevel ++ fd (\n) writestring indent
	/CNT 1 store
	%| maintain CNT to count bytes.  wrap lines at a reasonable
	%| place when writing out character names, to avoid long lines
	{ %forall
	    dup type /integertype eq { %ifelse
		fd (\040) writestring
		scratch cvs fd exch writestring /CNT CNT 4 add store
	    }{ %else
		fd (/) writestring
		dup type /nametype eq { scratch cvs }{ pop (.notdef) } ifelse
		dup  length 1 add CNT add /CNT exch store  fd exch writestring
	    } ifelse
	    CNT 60 ge { /CNT 1 store fd (\n) writestring indent } if
	} forall
	/indentlevel -- fd (\n) writestring indent fd (]) writestring
    } bdef
 
  % write numbers in various formats:
 
    /thruCTM { CTM transform } bdef
    /dthruCTM { CTM dtransform } bdef
    /XthruCTM { %def
	dup CTM dtransform
	rot not { pop }{ %else
	    2 copy gt { pop }{ exch pop } ifelse
	} ifelse
    } bdef

    /*writestring { %def
	writestring fd *flushfile
    } bdef
    /shave { %def
      % eliminate significant digits beyond .0001; compensate for roundoff
	dup type /realtype eq { %if
	    10000 mul round 10000 div
	} if
    } bdef
    /writenum { % def		% num :
	dup abs 0.001 le { pop 0 } if		% --> 0
	dup dup cvi eq { cvi } if
	fd exch scratch cvs writestring _space
    } bdef
    /writeprecisenum { % def		% num :
	fd exch scratch cvs writestring _space
    } bdef
    /writeXnum { % def		% num :
	CTM 0 get mul writenum
    } bdef
    /writeYnum { % def		% num :
	CTM 3 get mul writenum
    } bdef
    /writeTpair { % def		% num1 num2 :
	thruCTM exch
	writenum writenum
    } bdef
    /writepair { % def		% num1 num2 :
	exch writenum writenum
    } bdef
    /writenumarray {		% [ nums ] : 
	fd ([) writestring
	{ writenum } forall
	fd (] ) writestring
    } bdef
 
  % write out names and strings:
    /rprint /print load def
    /r= /= load def
%    /print { fd exch writestring } bind def
%    /= { scratch cvs fd exch writestring writeNL } bind def

    /writeNL { fd (\n) writestring } bdef
    /_space { fd (\040) writestring } bdef
    /wout { % def		% (string) :
	 fd exch writestring
    } bdef
    /writestr { % def		% (string) :
	fd exch writestring _space
    } bdef
    /writeop { %def		% (string) :
	fd exch writestring writeNL
    } bdef
    /writePSstring { % def	% (string) :
	fd (\() writestring dup length 75 gt exch
	wordfix fd (\) ) writestring { writeNL } if % if length > 75 bytes
    } bdef
    % formathexstring, thanks to Anders Blomdell
    %	file string linelength formathexstring
    /formathexstring { %def
	hexformat 2 idiv 1 index length
	0 2 index 2 index { %for
	    dup 3 index add 2 index lt { %ifelse
		2 index
	    }{ %else
		dup 2 index sub neg
	    } ifelse
	    4 index 3 1 roll getinterval 
	    4 index exch writehexstring writeNL
	} for
	pop pop pop pop
    } bdef
    /writename { % def		% name :
	scratch cvs fd exch writestring  _space
    } bdef
    /writeRname { % def		% name :
	(/) wout scratch cvs wout (R ) wout
    } bdef
    /checkusernames { %def	% array :
	{ % forall
	    dup type /nametype ne { pop }{ %ifelse
		dup systemdict exch known { pop }{ % ifelse
		    dup xcheck not { pop }{ %ifelse
			dup unames exch known { pop }{ %ifelse
			    dup where not { %ifelse
				dup unames exch true put
				pop % assume it's taken care of
			    }{ %else
				pop dup load dup type /arraytype eq
				1 index type /packedarraytype eq or
				  { checkusernames }{ pop } ifelse
				indent (userdict /) wout dup writename
				dup unames exch true put
				load writeANY
				(put) writeop indent
			    } ifelse
			} ifelse
		    } ifelse
		} ifelse
	    } ifelse
	} forall
    } bdef
    /arrayusernames { %def
	dup type /arraytype eq 1 index type /packedarraytype eq or { %ifelse
	    dup checkusernames
	    { arrayusernames } forall
	}{ pop } ifelse
    } bdef
    /writeproc { %def
	({) writestr
	insideproc exch /insideproc true store
	dup type /arraytype eq 1 index type /packedarraytype eq or { % ifelse
	    dup length 20 lt { %ifelse
		{ writeANY } forall
	    }{ %else
		writeNL /indentlevel ++ indent
		{ writeANY writeNL indent } forall
		/indentlevel -- writeNL indent
	    } ifelse
	}{ %else
	    writename
	} ifelse
	/insideproc exch store
	(} ) writestr
    } bdef
    /typedict 12 dict def
    typedict begin
	/stringtype {
	    dup 0 get 0 eq 1 index dup length 1 sub get 0 eq or {
		(<) wout fd exch formathexstring (> ) wout
	    }{ writePSstring } ifelse
	} bdef
	/arraytype { %def
	    % dup checkusernames
	    dup xcheck { %ifelse
		writeproc
	    }{ %else
		/CNT 1 store
		dup length 20 lt { %ifelse
		    ([ ) wout { writeANY } forall (] ) wout
		}{ %else
		    ([) writeop /indentlevel ++
		    { indent writeANY writeNL } forall
		    /indentlevel -- indent (] ) wout
		} ifelse
	    } ifelse
	} bdef
	/packedarraytype /arraytype load def
	/dicttype { %def
			  % safety: 1 add (needed for User Fonts)
	    dup maxlength 1 add writenum (dict begin) writeop indent
	    { %forall
		exch writeANY writeANY (def ) writeop indent
	    } forall (currentdict end ) wout
	} bdef
	/integertype { writenum } def
	/realtype { writeprecisenum } def
	/nulltype { pop (null ) wout } def
	/operatortype { %def
	    insideproc { %ifelse
		writename
	    }{ %else
		(/) wout writename (load) writestr
	    } ifelse
	} bdef
	/nametype { %def
	    dup xcheck not { (/) wout dup unames exch true put } if
	    writename
	} bdef
    end % typedict
    /writeANY { %def 
	dup type dup typedict exch known { %ifelse
	    typedict exch get exec
	}{ %else
	    pop writename
	} ifelse
    } bdef
    % The following writes an escaped string that may contain special chars.
    % It regenerates the (\035string) notation.
    /wordfix { %def		% (string) :
	(\() search { %ifelse
	    rparenfix (\\\() wout pop wordfix
	}{ rparenfix } ifelse
    } bdef
    /rparenfix { %def
	(\)) search { %ifelse
	    binaryfix (\\\)) wout pop rparenfix
	}{ binaryfix } ifelse
    } bdef
    /str1 1 string def
    /longstr 1028 string def
    /writetomark { %def
	counttomark -1 0 { %for
	    longstr exch exch put
	} for
    } bdef
    /binaryfix { %def
	dup false exch { %forall
	    dup 128 gt 1 index 32 lt or { %ifelse
		str1 exch 0 exch put pop true exit
	    }{ pop } ifelse
	} forall
	{ %ifelse	% depending on whether binary num was found
	    str1 search {
		quotefix		% string previous to binary num
		(\\) wout		% the backslash
		0 get dup 8 eq {
		    pop (b) wout
		}{ %else
		    dup 10 eq {
			pop (n) wout
		    }{ %else
			% write binary char as octal: \008
			8 scratch cvrs
			dup length 3 exch sub { (0) wout } repeat wout
		    } ifelse
		} ifelse
		binaryfix		% recurse on rest of string
	    }{
		(ERROR: search lied in "binaryfix".) r= flush stop
	    } ifelse
	}{ quotefix } ifelse
    } bdef
    /quotefix { %def
	(\\) search {  %ifelse
	    wout (\\\\) wout pop quotefix
	}{ wout } ifelse
    } bdef

end %adobe_distill
/setpacking where { pop setpacking } if
%%EndProcSet distill 1.0 0

%%BeginProcSet: distill_graphicstate 1.0 0
% we don't want packed arrays for all these matrices; set packing later
/adobe_distill dup where { pop pop }{ 165 200 add dict def } ifelse
adobe_distill begin
 
  % define a bunch of state variables, then use "store" subsequently
  % to write into them (to avoid currentdict problems).
    /mtx matrix def
    /tmpmtx matrix def
    /fontmtx matrix def
    /curfontmtx matrix def
    /CTM matrix currentmatrix def
    /normalCTM tmpmtx currentmatrix matrix invertmatrix def
    /compareCTM matrix currentmatrix def
    /newCTM matrix def
    /mtx1 0 def
    /mtx2 0 def
    /$normalize {
	dup tmpmtx copy normalCTM 3 -1 roll concatmatrix
    } bind def
    /rot false def
    /gray currentgray def
    currentcmykcolor
    /colK exch def /colY exch def /colM exch def /colC exch def
    /linewidth currentlinewidth def
    /linecap currentlinecap def
    /linejoin currentlinejoin def
    /miterlimit currentmiterlimit def
    /screenang null def
    /screenfreq null def
    /screenproc null def
    /closed false def
    currentdash /dashoff exch def /dasharray exch def
    /pointX -1 def /pointY -1 def
    /initfontscale { 1 0 0 1 0 0 $fontscale astore pop } bind def
    /$fontscale matrix  def
    /0a 0 def /0b 0 def
    /X1 0 def /X2 0 def
    /origfontname null def
    /currfontdict null def
    /definefontname null def
    /tempfontname /Courier def
%    /defaultfontname substitutefonts { /Courier }{ /Unknown } ifelse def
    /defaultfontname {
	/FontType where { %ifelse
	    pop FontType 3 eq {
		FontInfo /realname get
	    }{ substitutefonts { /Courier }{ /Unknown } ifelse } ifelse
	}{ %else
	    substitutefonts { /Courier }{ /Unknown } ifelse
	} ifelse
    } def
    /ischarpath false def
    /currpath newpath hashpath def
    /pathstr () def
    /pathbool false def
    /pathX 0 def /pathY 0 def
    /lineX 0 def /lineY 0 def
    /closeX 0 def /closeY 0 def
    /lcount 0 def /rcount 0 def
    /REPEAT_LINETO_THRESHOLD 20 def	% point at which repeat loop is used
    /currX -1 def /currY -1 def
    /diffX 0 def
    /gstates 0 def
    /charpathgstate 0 def
    /CNT 0 def
    /showX null def /showY null def
    /currfont currentfont def
    /cliphash newpath hashpath def
    /?simplepath false def
    /simplepath [ 0 0 0 0 ] def

/setpacking where { pop currentpacking true setpacking } if
 
    /matrixeq { %def		% compares two matrices
	/mtx2 exch store
	/mtx1 exch store
	0 1 5 { %for
	    dup mtx1 exch get
	    exch mtx2 exch get eq
	} for
	5 { and } repeat
    } bdef
    % begin eqarray AB 890420 (thanks to Anders Blomdell)
    %   array1 array2 eqarray bool
    /arrayeq {
      % if they're equal, they're equal: simplicity first...
	2 copy eq { pop pop true }{ %ifelse
	    % next check their lengths, for trivial eq/ne:
	    2 copy length exch length eq { %ifelse
		% We now have to compare all elements
		true				% arr arr true
		0 1 3 index length 1 sub	% arr arr true 0 1 length-1
		{				% arr arr bool index
		  3 index 1 index get		% arr arr bool index val1
		  3 index 2 index get		% arr arr bool index val1 val2
		  eq exch pop and		% arr arr bool
		} for
		exch pop exch pop
	    }{ pop pop false } ifelse
	} ifelse
    } bdef
    /arrayne {
      arrayeq not
    } bdef
 
  % procedure definitions for state machinery ---------------
 
    /initgstate { %def
	gsave
	    initgraphics
	    /CTM mtx currentmatrix $normalize store
	    tmpmtx currentmatrix compareCTM matrixeq not {
		.345 dup 0 dtransform pop 0 idtransform
		pop ne dup /rot exch store not optimize and /optim exch store
	    } if
	    compareCTM currentmatrix pop
	    /gray currentgray store
	    currentcmykcolor
	    /colK exch store /colY exch store
	    /colM exch store /colC exch store
	    /linewidth currentlinewidth XthruCTM store
	    /linecap currentlinecap store
	    /linejoin currentlinejoin store
	    /miterlimit currentmiterlimit store
	    currentdash /dashoff exch store /dasharray exch store
	    /origfontname /InvalidFont store
	    /definefontname /InvalidFont store
	    initfontscale
	    /currfontdict currentfont store
	    currentscreen
	    /screenproc exch store
	    /screenang exch store
	    /screenfreq exch store
	    /cliphash clippath hashpath store	% Wed Dec 28 12:41:07 1988
	grestore
    } bdef % initgstate
    /forcegstate { %def
	% after save & restore, you may have to explicitly "undo" anything
	% that was done within the saved context.  Since save & restore
	% affect all our state variables, we dump anything that is different
	% from the default graphics state:
	/CTM [1.01 0 1.01 0 .5 .5] store
	/compareCTM [1.01 0 1.01 0 .5 .5] store
	initfontscale
	/currfontdict null store
	/gray null store
	/colC null store
	% checkgstate % fontstate
	currentfont null ne { % if
	    currentfont dup /FontInfo known { %ifelse
		/FontInfo get dup /pleasemap known { %ifelse
		    begin /pleasemap true hidebool end
		}{ pop } ifelse
	    }{ pop } ifelse
	} if
    } bdef % initgstate
    /checkgstate { %def
	graphicstate
	fontstate
    } def %checkgstate
    /checkCTM { %def
	tmpmtx currentmatrix compareCTM matrixeq not {
	    % /CTM mtx currentmatrix $normalize store
	    CTM currentmatrix $normalize pop
	    compareCTM currentmatrix $normalize pop
	    .345 dup 0 dtransform pop 0 idtransform
	    pop ne dup /rot exch store not optimize and /optim exch store
	} if
    } bdef
    /generalstate { %def
	stackptr 0 ne { stackshow } if
	/lastshow false store
	checkCTM
    } bdef % generalstate
    /colorstate { %def
	mark currentcmykcolor
	colC colM colY colK 4 { %repeat
	    dup 5 index ne 10 1 roll 8 1 roll
	} repeat
	cleartomark or or or {
	    currentcmykcolor
	    /colK exch store /colY exch store
	    /colM exch store /colC exch store
	    colC 0 eq colM 0 eq colY 0 eq and and not { %ifelse % COLOR
		colC writenum colM writenum colY writenum colK writenum
		(C) writeop
	    }{ %else						% GRAY
		1 colK sub shave writenum (g) writeop
	    } ifelse
	} if
    } bdef % colorstate
    /registerfont { %def
	% dup =string cvs print ( registered ) print 1 index == flush
	dup cachedir exch 20 dict put	% allow 20 point sizes
	cachedir exch get		% ptsize dict
	exch fontcount put
    } bdef
    /addfontsize { %def
	% dup =string cvs print ( point size ) print 1 index == flush
	cachedir exch get
	exch fontcount put
    } bdef

    /fontstate { %def
      currentfont null eq not	{ %if
	currentfont dup /ScaleMatrix known not { pop }{ %ifelse
	    begin
	     % determine if anything has changed:
		tmpmtx currentmatrix compareCTM matrixeq not
		currfontdict currentfont ne or
		ScaleMatrix CTM tmpmtx concatmatrix $fontscale matrixeq not or
		{ %if
		  % get and set new font names
		    /origfontname
			/FontInfo where { %ifelse
			    pop FontInfo /realname known
			    { FontInfo /realname get }{ % ifelse
				currentdict /FontName known { FontName }{
				    defaultfontname
				} ifelse
			    } ifelse
			}{ %else
			    currentdict /FontName known { FontName }{
				defaultfontname
			    } ifelse
			} ifelse
		    store
		    /definefontname
			currentdict /FontName known { FontName }{
			    origfontname
			} ifelse
			FontDirectory { %forall
			    currentdict eq
			    { exch pop exit }
			    { pop } ifelse
			} forall
		    store
		    origfontname hidefontname
		 % check for font reencoding:
		 % The current font is the one required in the distilled
		 % program.  If it is a reeconded font, we must generate
		 % a call to "REMAP", but at the same time let's mark it
		 % so we don't generate too may "REMAP" calls.
 
		    checksetup generalstate colorstate
		 % worry about reencoding:
		    /FontInfo where { %ifelse
			pop FontInfo /pleasemap known { %ifelse
			    FontInfo /pleasemap get cvbool
			}{ %else
			    false  % evidently has not been reencoded...
			} ifelse % leaves a boolean
		    }{ false } ifelse
		    { % if remapping has not been done yet:
			Encoding hashencoding
			origfontname findfont /Encoding get hashencoding
			ne { %ifelse
			    Encoding hashencoding
			    STDvec cvnum eq { %ifelse
				(stdvec) writestr
				origfontname writeRname
				origfontname (/) wout writename
				( REMAP) writeop
			    }{ %else
			      Encoding hashencoding PAGEvec cvnum eq {
				  (pagevec) writestr
				  origfontname writeRname
				  origfontname (/) wout writename
				  ( REMAP) writeop
			      }{ %else
				  origfontname findfont /Encoding get Encoding
				  diffencoding writediffencoding
				  origfontname writeRname
				  origfontname (/) wout writename
				  ( RECODE) writeop
			      } ifelse
			    } ifelse
			    /FontInfo where { %if
				pop FontInfo /pleasemap known { %if
				    FontInfo begin
				        /pleasemap false hidebool
				    end
				} if
			    } if
			} if
		    } if % /pleasemap
		 % check font scale change:
		 % This stuff is absolutely horrible....
		    ScaleMatrix CTM $fontscale concatmatrix
 		    aload pop			    % Xscale 0a 0b Yscale 0 0
		    pop pop 3 1 roll			% X Y 0b 0a
		   % if 0a and 0b are really both 0 ...
		   % and X Y are equal and positive, then you can use
		   % "scalefont", else you have to use "makefont"
		    /0a exch store /0b exch store
		    /X1 exch store /X2 exch store
 		    X1 X2			% leave on stack
		    0a 0b eq 0b 0 eq and	% make sure 0's are 0
 		    X1 X2 EQ and		% X1 and X2 are equal
 		    X1 dup abs eq X2 dup abs eq and	% and positive
		    and
		    { %ifelse
			pop dup dup round EQ { round } if
		     % if you find it in the "font dict cache"....
			cachedir definefontname known { %ifelse
			    cachedir definefontname get dup 2 index known {
				exch get (F) wout writenum
				(F) writeop
			    }{ %else
				pop
				/fontcount ++
				dup definefontname addfontsize
				(/F) wout fontcount writenum %+ cvnum writenum
				origfontname
				/FontInfo where { %ifelse
				    pop FontInfo /pleasemap known { %ifelse
					FontInfo /pleasemap get cvbool
				    }{ false } ifelse % leaves a boolean
				}{ false } ifelse
				Encoding hashencoding
				origfontname findfont /Encoding get
				hashencoding ne and
				{ %ifelse
				    writeRname
				}{ (/) wout writename } ifelse
				writenum % point size
				(DF) writeop
			    } ifelse
			}{ %else if you DON'T find the name in the cache
			    cachefonts { %if
				/fontcount ++
				dup definefontname registerfont
				(/F) wout fontcount writenum
			    } if
			    origfontname  % either "FontName" or "FontNameR"
			    /FontInfo where { %ifelse
				pop FontInfo /pleasemap known { %ifelse
				    FontInfo /pleasemap get cvbool not
				}{ false } ifelse % leaves a boolean
			    }{ false } ifelse
			    Encoding hashencoding
			    origfontname findfont /Encoding get
			    hashencoding ne and
			    { %ifelse
				writeRname
			    }{ (/) wout writename } ifelse
			    writenum % point size
			    cachefonts { (DF) }{ (FF) } ifelse writeop
			} ifelse
		    }{ %else
		     % need either "makefont" or rotated coordinate system
			% careful.... there's still stuff on the stack.
			origfontname
			/FontInfo where {
			    pop FontInfo /pleasemap known
			}{ false } ifelse { %ifelse
			    writeRname
			}{ (/) wout writename } ifelse
			pop pop $fontscale aload pop curfontmtx astore
			dup 4 ScaleMatrix 4 get put
			dup 5 ScaleMatrix 5 get put  % no translate
			writenumarray
			(MF) writeop
		    } ifelse
		    /currfontdict currentfont store
		} if % anything has changed
	    end
	} ifelse
	beginsetup cvbool not {
	    generalstate
	    colorstate
	} if
      } if
    } bdef %fontstate

    /graphicstate { %def
	checksetup
	generalstate
	colorstate
	linewidth currentlinewidth XthruCTM ne {
	    /linewidth currentlinewidth XthruCTM store
	    linewidth shave writenum (w) writeop
	} if
	linecap currentlinecap ne {
	    /linecap currentlinecap store
	    linecap writenum (setlinecap) writeop
	} if
	linejoin currentlinejoin ne {
	    /linejoin currentlinejoin store
	    linejoin writenum (j) writeop
	} if
	miterlimit currentmiterlimit ne {
	    /miterlimit currentmiterlimit store
	    miterlimit shave writenum (setmiterlimit) writeop
	} if
	currentdash dashoff ne exch dasharray arrayne or {
	    currentdash /dashoff exch store /dasharray exch store
	    fd ([) writestring
	    dasharray { XthruCTM writenum } forall
	    fd (] ) writestring
	    dashoff XthruCTM writenum (d) writeop
	} if
	gsave
	  % don't clip to degenerate paths of any kind:
	    newpath clippath hashpath cliphash ne { %if
		mark { pathbbox } stopped not {
		    exch 4 -1 roll sub abs 1 gt
		    3 1 roll sub abs 1 gt and { % if
			writepath
			(clip newpath) writeop
			/cliphash hashpath store
		    } if
		} if cleartomark
	    } if
	grestore
	currentscreen
	/screenproc load ne exch screenang ne or exch screenfreq ne or { %if
	    currentscreen
	    /screenproc exch store
	    /screenang exch store
	    /screenfreq exch store
	    screenfreq writenum screenang writenum writeNL
	    /screenproc load
	    dup type /arraytype eq
	    1 index type /packedarraytype eq or { %ifelse
		checkusernames
	    }{ pop } ifelse
	    /screenproc load writeproc
	    (setscreen) writeop
	} if
    } bdef %graphicstate

end %adobe_distill
/setpacking where { pop setpacking } if
%%EndProcSet distill_graphicstate 1.0 0

%%BeginProcSet: distill_optimize 1.0 0
/adobe_distill dup where { pop pop }{ 165 200 add dict def } ifelse
adobe_distill begin
  % These procedures implement an optimization scheme for recognizing
  % sequences of "show" operations that could be optimized into calls
  % to "widthshow" (or just "show" with a longer string body).  In
  % order to accomplish this, we have implemented a stack to store
  % string bodies until they are flushed by a font change, a change
  % in Y coordinate, or an inter-string space that is inconsistent.
  % When comparing coordinates for equality, anything with the given
  % tolerance is accepted as being equal (to combat roundoff error).
    /tolerance .05 ifnotdef
    /EQ { sub abs tolerance le } bdef
    /stack 250 array def
    /stackptr 0 def
/setpacking where { pop currentpacking true setpacking } if
    /push { %def
	stackptr 0 eq { % if
	    currentpoint thruCTM
	    /showY exch store /showX exch store
	} if
	/stackptr stackptr 1 add store
	  stackptr 249 ge { (STACK OVERFLOW!) r= flush exit } if
	stack stackptr 3 -1 roll put
    } bdef
    /pull { %def
	stack stackptr get
	/stackptr stackptr dup 0 gt { 1 sub } if store
    } bdef

    /*save systemdict /save get def
    /save { % def
	stackshow	% in case there's anything pending....
	*save
    } bdef

    /*restore systemdict /restore get def
    /restore { % def
	% after save & restore, you may have to explicitly "undo" anything
	% that was done within the saved context.  Since save & restore
	% affect all distillery state variables, we dump anything different
	% from the default graphics state:
	stackshow	% in case there's anything pending....
	  currentlinecap	% 5
	  currentlinewidth	% 4
	  currentgray		% 3
	  currentmiterlimit	% 2
	  currentlinejoin	% 1
	    6 -1 roll *restore
	  setlinejoin		% 1
	  setmiterlimit		% 2
	  setgray		% 3
	  setlinewidth		% 4
	  setlinecap		% 5
	forcegstate % checkgstate %graphicstate
    } bdef

    /stackshow { %def
	stackptr 0 ne { %if
	    messages {
		(stackshow: ) d=
		1 1 stackptr { (  ) pr= stack exch get == } for
	    } if
% 	    currfont /FontType known {
% 		currfont /FontType get 3 eq {
% 		    ?distilling false setdistill
% 		} if
% 	    } if
	    stackptr 1 eq { %ifelse
		%- if there is only one string, use "show":
		pull writePSstring
		showX showY writepair (T) writeop
	    }{ %else
		%- otherwise, build single string (with \b to use W):
		diffX 0 EQ not { % if
		    gsave		% figure out widthshow value
			currfont setfont
			diffX (\b) stringwidth CTM dtransform pop sub
		    grestore
		    writenum (0) writestr (\b) 0 get writenum
		    (\\b)	% padding character
		}{ % else
		    ()		% empty padding character
		} ifelse
		(\() wout
		1 1 stackptr 1 sub { % for
		    stack exch get wordfix dup wout
		} for
		pop		% padding character
		pull wordfix
		(\)) wout % writeNL
		showX showY writepair
		%- if diffX is 0, don't use "widthshow":
		diffX 0 EQ { (T) }{ (W) } ifelse writeop
	    } ifelse
	    /stackptr 0 store
% 	    currfont /FontType known {
% 		currfont /FontType get 3 eq { setdistill } if
% 	    } if
	} if
    } bdef

    /setcurrpoint { %def
	currentpoint thruCTM
	/currY exch store /currX exch store
    } bdef % setcurrpoint

end %adobe_distill
/setpacking where { pop setpacking } if
%%EndProcSet distill_optimize 1.0 0

%%BeginProcSet: distill_paintops 1.0 0
/setpacking where { pop currentpacking true setpacking } if
/adobe_distill dup where { pop pop }{ 165 200 add dict def } ifelse
adobe_distill begin

  % text operators
    /sameYcoords { %def
      % this is pulled out of the "show" proc for readability; it is
      % not used anywhere else
	currentfont currfont ne { %ifelse
	    stackshow fontstate push
	}{ %else
	    currentpoint thruCTM pop
	    currX sub dup diffX EQ { %ifelse
		pop 	% dup'ed value
		push
	    }{ %else
		diffX -1 eq { %ifelse
		    /diffX exch store push
		}{ % else
		    pop stackshow fontstate
		    /diffX -1 store push
		} ifelse
	    } ifelse
	} ifelse
    } bdef

    /*stringwidth /stringwidth load def
    /stringwidth { %def
	false setdistill *stringwidth true setdistill
    } bdef
    /show { %def
	checkCTM currentpoint thruCTM ?box
	optim { %ifelse
	    dup length 0 eq { pop } { %ifelse
		dup			% save string for use at the end
		lastshow not { %ifelse
		    stackshow fontstate
		    /currfont currentfont store
		    push
		    /diffX -1 store
		}{ % else
		  % don't optimize if matrix is different...
		    tmpmtx currentmatrix compareCTM matrixeq
		    currentpoint thruCTM exch pop
		    currY eq and { %ifelse		Y = Y
			sameYcoords
		    }{ %else currY ne
			stackshow	% flush the pending show stack
			fontstate
			push		% the string (and set showX, showY)
			/diffX -1 store
		    } ifelse
		    /currfont currentfont store
		} ifelse %lastshow
		currentfont dup null ne { /FontType known }{ pop false } ifelse
		{	%gcr Fri May  5 15:22:16 1989
		    currentfont /FontType get 3 eq {
			false setdistill show true setdistill
		    }{ show } ifelse
		}{ false setdistill show true setdistill } ifelse
		setcurrpoint
		/lastshow true store
	    } ifelse % if length is not 0
	}{ % else
	    dup length 0 eq { pop } { %ifelse
		fontstate
		dup writePSstring currentpoint writeTpair
		(T) writeop
		currentfont dup null ne { /FontType known }{ pop false } ifelse
		{	%gcr Fri May  5 15:22:45 1989
		    currentfont /FontType get 3 eq {
			false setdistill show true setdistill
		    }{ show } ifelse
		}{ false setdistill show true setdistill } ifelse
	    } ifelse % if operand is not null string
	} ifelse
	currentpoint thruCTM ?box
    } bdef

    /widthshow { %def
	checkCTM currentpoint thruCTM ?box
	optim { %ifelse
	    dup length 0 eq { 4{pop}repeat } { %ifelse
		4 copy pop pop
		1 index EQ exch 0.0 EQ and { % ifelse
		    fontstate
		    4 1 roll pop pop pop
		    show	% make sure it's not "bound"
		}{ %else
		    fontstate
		    4 copy
		    4 2 roll dthruCTM writepair %exch writeXnum writeYnum
		    exch writenum writePSstring currentpoint writeTpair
		    (W) writeop
		    currentfont dup null ne {
			/FontType known
		    }{ pop false } ifelse
		    { %ifelse
			currentfont /FontType get 3 eq {
			    false setdistill widthshow true setdistill
			}{ widthshow } ifelse
		    }{ false setdistill widthshow true setdistill } ifelse
		} ifelse
	    } ifelse
	}{ %else
	    % Cx Cy char (string) widthshow
	    dup length 0 eq { 4{pop}repeat } { %ifelse
		fontstate
		4 copy
		% 4 -2 roll exch writeXnum writeYnum exch writenum
		4 -2 roll dthruCTM writepair exch writenum
		writePSstring currentpoint writeTpair
		(W) writeop
		currentfont dup null ne { /FontType known }{ pop false } ifelse
		{ %ifelse
		    currentfont /FontType get 3 eq {
			false setdistill widthshow true setdistill
		    }{ widthshow } ifelse
		}{ false setdistill widthshow true setdistill } ifelse
	    } ifelse
	} ifelse
	currentpoint thruCTM ?box
    } bdef

    /ashow { %bdef
	checkCTM currentpoint thruCTM ?box
	optim { %ifelse
	    dup length 0 eq { pop pop pop } { %ifelse
		3 copy pop
		1 index EQ exch 0.0 EQ and { % ifelse
		    fontstate
		    3 1 roll pop pop
		    show	% make sure it's not "bound"
		}{ %else
		    fontstate
		    3 copy
		    3 1 roll dthruCTM writepair
		    writePSstring currentpoint writeTpair
		    (A) writeop
		    currentfont dup null ne { %ifelse
			/FontType known
		    }{ pop false } ifelse
		    { %ifelse
			currentfont /FontType get 3 eq {
			    false setdistill ashow true setdistill
			}{ ashow } ifelse
		    }{ false setdistill ashow true setdistill } ifelse
		} ifelse
	    } ifelse
	}{ %else
	    dup length 0 eq { pop pop pop } { %ifelse
		fontstate
		3 copy
		3 1 roll dthruCTM writepair % exch writeXnum writeYnum
		writePSstring currentpoint writeTpair
		(A) writeop
		currentfont dup null ne { %ifelse
		    /FontType known
		}{ pop false } ifelse
		{ %ifelse
		    currentfont /FontType get 3 eq {
			false setdistill ashow true setdistill
		    }{ ashow } ifelse
		}{ false setdistill ashow true setdistill } ifelse
	    } ifelse
	} ifelse
	currentpoint thruCTM ?box
    } bdef

    /awidthshow { %def
	% Cx Cy 32 Ax Ay (string) awidthshow
	checkCTM currentpoint thruCTM ?box
	optim { %def
	    dup length 0 eq { 6{pop}repeat } { %ifelse
		fontstate
		6 copy 6 1 roll
		1 index EQ exch 0.0 EQ and { %ifelse
		    4 1 roll 1 index eq exch 0.0 eq and { %leaves 32 (str)
			8 1 roll 7 { pop } repeat
			show	% make sure it's not "bound"
		    }{ %else
			pop pop 3 1 roll pop pop
			widthshow	% make sure it's not "bound"
		    } ifelse
		}{ %else
		    pop pop pop pop 6 copy 6 -3 roll pop
		    1 index EQ exch 0.0 EQ and { % ifelse
			9 3 roll 6 { pop } repeat
			ashow	% make sure it's not "bound"
		    }{ %else
			pop pop pop 6 copy
			6 -2 roll dthruCTM writepair
			4 -1 roll writenum 3 1 roll dthruCTM writepair
			writePSstring currentpoint writeTpair
			(AW) writeop
			currentfont /FontType known {
			    currentfont /FontType get 3 eq {
				false setdistill awidthshow true setdistill
			    }{ awidthshow } ifelse
			}{ false setdistill awidthshow true setdistill } ifelse
		    } ifelse
		} ifelse
	    } ifelse
	}{ %else
	    dup length 0 eq { 6{pop}repeat } { %ifelse
		fontstate
		6 copy
		% 6 -2 roll exch writeXnum writeYnum
		% 4 -1 roll writenum 3 -1 roll writeXnum exch writeYnum
		6 -2 roll dthruCTM writepair
		4 -1 roll writenum 3 1 roll dthruCTM writepair
		writePSstring currentpoint writeTpair
		(AW) writeop
		    currentfont /FontType known {
			currentfont /FontType get 3 eq {
			    false setdistill awidthshow true setdistill
			}{ awidthshow } ifelse
		    }{ false setdistill awidthshow true setdistill } ifelse
	    } ifelse
	} ifelse
	currentpoint thruCTM ?box
    } bdef

    /kshow { %def
	(%AAAAAH: kshow) writeop
	kshow
    } bdef

   % graphics operators
    /fillguts { %def
	(starting fill) d=
	generalstate
	graphicstate
	% do nothing for empty path!
	hashpath -1 ne { writepath } if		% watch for empty path!
	ischarpath { % if
	    pathstr length 0 gt {
		pathX writenum pathY writenum (m) writeop
		pathstr writePSstring (false charpath) writeop
	    } if
	    gstates 0 le {
		/ischarpath false store
		/closed false store
	    } if
	} if
    } bdef

    /fill { %def
	?distilling cvbool { %if
	    fillguts
	    ?simplepath {
		simplepath aload pop
		4 2 roll writepair (moveto) writeop writepair (lineto) writeop
		/?simplepath false store
	    } if
	    hashpath -1 ne { (f) writeop } if
	} if
	fill
    } bdef
    /eofill { %def
	?distilling cvbool { %if
	    fillguts
	    ?simplepath { %ifelse
		simplepath aload pop
		4 2 roll writepair (moveto) writeop writepair (lineto) writeop
		/?simplepath false store
	    } if
	    hashpath -1 ne { (eofill) writeop } if
	} if
	eofill
    } bdef

    /stroke { %def
	?distilling cvbool { %if
	    fillguts
	    ?simplepath { %ifelse
		generalstate graphicstate
		simplepath aload pop
		4 copy 3 -1 roll eq { %ifelse
		    pop pop 4 -1 roll 2 index sub writenum
		    writepair (X) writeop pop
		}{ %else
		    eq { %ifelse
			3 -1 roll 1 index sub writenum
			writepair (Y) writeop pop
		    }{ %else
			writepair writepair (l) writeop
		    } ifelse
		} ifelse
		%% writepair writepair (l) writeop
		/?simplepath false store
	    }{ % else
		closed { (cp ) wout } if
		hashpath -1 ne { (s) writeop } if
	    } ifelse
	} if
	stroke
    } bdef

    /clip { %def
	?distilling cvbool { %if
	    /lastshow false store
	} if
	clip
    } bdef
    /eoclip /clip load def
    /imageguts { % def
	graphicstate
	/imageproc exch store
	/imagematrix exch store
	/imagedepth exch store
	/imageheight exch store
	/imagewidth exch store
     % set up the call to "image" in the output file:
	(/imagesave save def) writeop
	CTM writenumarray (concat) writeop
	0 0 thruCTM ?box
	imagewidth imagedepth dup type /booleantype eq { pop 1 } if
	div imageheight imagematrix itransform thruCTM ?box
	(/imagebuff) writestr
	imagedepth dup type /booleantype eq { pop 1 } if
	imagewidth mul dup dup 8 idiv 8 mul eq {8 idiv}{8 idiv 1 add} ifelse
	writenum ( string def) writeop
     % invoke "image" with correct args in output file:
	imagewidth writenum imageheight writenum
	imagedepth (     ) cvs writestr
	imagematrix writenumarray
    } bdef
    /image { %def	% width height depth matrix { proc } :
	?distilling cvbool { %ifelse
	    imageguts
	    ({ currentfile imagebuff readhexstring pop } image) writeop
	    imagewidth imageheight imagedepth imagematrix
	    { imageproc dup fd exch formathexstring writeNL } image
	    (imagesave restore) writeop
	}{ image } ifelse
    } bdef
    /imagemask { % def	% width height depth matrix { proc } :
	?distilling cvbool { %ifelse
	    imageguts
	    ({ currentfile imagebuff readhexstring pop } imagemask) writeop
	    imagewidth imageheight imagedepth imagematrix
	    { imageproc dup fd exch formathexstring writeNL } imagemask
	    (imagesave restore) writeop
	}{ imagemask } ifelse
    } bdef
    % don't actually print the pages...   Fri Feb 17 13:13:10 1989
    % /*showpage systemdict /showpage get def
    /*showpage where { pop }{ %ifelse
	/*showpage /showpage load def
    } ifelse
    /showpage { %def
	stackshow
	pagecount cvnum scratch cvs wout ( ENDPAGE\n) wout
	(%%PageTrailer) writeop
	(%%PageFonts: ) wout
	pfontcount cvnum 0 eq { writeNL }{ %else
	    pfontcount cvnum 200 lt { %ifelse
		pagefonts 0 pfontcount cvnum getinterval writeop
	    }{ %else
		pagefonts (\040) search not { writeop }{ %else
		    writeop	% first one without the %%+
		    { %loop
			search { (%%+ ) wout writeop }{ %else
			    (\000) search { writeop pop pop }{ pop } ifelse
			    exit
			} ifelse
		    } loop
		} ifelse
	    } ifelse
	} ifelse
	0 1 pfontcount cvnum { pagefonts exch 0 put } for
	/pfontcount 0 hideval
	LLx 10000 eq LLy 10000 eq or URx -10000 eq URy -10000 eq or or not {
	    (%%PageBoundingBox: ) wout
	      LLx cvnum writenum LLy cvnum writenum
	      URx cvnum writenum URy cvnum writenum writeNL
	    pageBBox-docBBox
	} if
	/LLx 10000 hideval  /LLy 10000 hideval
	/URx -10000 hideval /URy -10000 hideval
	*showpage
	checksetup
	/lastshowpage true hidebool
	/begunpage false hidebool
	/PAGEvec 0 hideval
    } bdef
    /*pathbbox systemdict /pathbbox get def
    /pathbbox { %def
	?distilling cvbool { %if
	    ischarpath { %ifelse
		gsave
		    { currentpoint } stopped { 0 0 } if
		    systemdict /moveto get exec
		    pathstr false charpath flattenpath *pathbbox
		grestore
	    }{ %else
		*pathbbox
	    } ifelse
	} if
    } bdef
    /gsave { % def
	?distilling cvbool { /gstates gstates 1 add store } if
	gsave
    } bdef
    /grestore { % def
	?distilling cvbool { %if
	    gstates 0 gt { %if
		/gstates gstates 1 sub store
		gstates charpathgstate lt { /ischarpath false store } if
	    } if
	} if
	grestore
    } bdef
    /charpath { %def
	% need to make sure that when "stroke" or "fill" comes along
	% that the "charpath" elements are in the right place in the path...
	%- writepath
	?distilling cvbool { %if
	    checkgstate
	    /ischarpath true store
	    /charpathgstate gstates store
	    /pathbool exch store
	    /pathstr exch store
	    { currentpoint } stopped { 0 0 } if thruCTM
	    /pathY exch store /pathX exch store
	    pathstr stringwidth rmoveto
	} if
    } bdef
    /newpath { %def
	?distilling cvbool { gstates 0 le { /ischarpath false store } if } if
	newpath
    } bdef

end %adobe_distill
/setpacking where { pop setpacking } if
%%EndProcSet: distill_paintops 1.0 0

%%BeginProcSet: distill_guessfont 1.0 0
/setpacking where { pop currentpacking true setpacking } if
/adobe_distill dup where { pop pop }{ 165 200 add dict def } ifelse
adobe_distill begin
    /*definefont systemdict /definefont get def
    /definefont { %def
	% make a dictionary into which to put things
	% put the ORIGINAL name of the font into that dictionary
	% put the original FID in that dictionary, for easy comparison
	dup /FontType known {
	    dup /FontType get 3 eq { %ifelse
		dup begin
		    includeuserfonts { %if
			(%%BeginFont: ) wout 1 index writename writeNL
			currentdict maxlength writenum (dict begin) writeop
			save
			    /indentlevel ++
			    unames /Encoding true put
			    currentdict { %forall
				exch dup /Encoding eq { %ifelse
				    indent (/) wout writename
				    writenamearray ( def) writeop indent
				}{ %else
				    % dup unames exch true put
				    ( /) wout writename writeANY
				    (def) writeop indent
				} ifelse
			    } forall
			    currentdict { pop unames exch true put } forall
			    currentdict { exch pop arrayusernames } forall
			restore
			indent (currentdict end\n) wout
			1 index writeANY (exch definefont pop) writeop
			(%%EndFont: ) wout 1 index writename writeNL
		    } if
		    currentdict /FontInfo known not
		    currentdict /FontName known not or
		    currentdict dup length 3 add exch maxlength ge and { %if
			% make slightly bigger version of current dictionary
			pop currentdict end
			dup maxlength 2 add dict begin
			{ def } forall currentdict
		    } if
		    /FontInfo 5 dict def
		    FontInfo begin
			/realname 2 index def
			/pleasemap magicbool def
			/pleasemap false hidebool
		    end
		    /FontName 2 index def
		end
		false
	    }{ true } ifelse
	}{ true } ifelse
	% previous code leaves either true or false on stack
	{ %if
	    /Dfont exch store
	 % This might be the first time we've ever seen a new
	 % encoding.  If so, let's guess that we'll see lots
	 % more of the vector, and give it the name "stdvec".
 	    Dfont begin
		%gcr FontType 1 eq STDvec cvnum 0 eq and
	        STDvec cvnum 0 eq
		Encoding StandardEncoding ne and { %if
		    /STDvec Encoding hashencoding hideval
		    fd (/stdvec\n) *writestring
		    STDvec
		    StandardEncoding hashencoding eq { %ifelse
			fd (StandardEncoding ) *writestring
		    }{ %else
			Encoding writenamearray
		    } ifelse
		    fd (def\n) *writestring
		    fd (stdvec /CourierR /Courier REMAP\n) *writestring
		    % checksetup
		}{ %else
		    %gcr FontType 1 eq STDvec cvnum 0 eq and
		    STDvec cvnum 0 eq
		    Encoding StandardEncoding ne and { %if
			/PAGEvec Encoding hashencoding hideval
			fd (/pagevec\n) *writestring
			PAGEvec
			StandardEncoding hashencoding eq { %ifelse
			    fd (StandardEncoding ) *writestring
			}{ %else
			    Encoding writenamearray
			} ifelse
			fd (def\n) *writestring
			% checksetup
		    } if
		} ifelse
	    end
	 % try to find the "real" font in FontDirectory from which this
	 % font was derived, assuming it was reencoded....
	    /tempfontname /Courier store
	    /tempfontname /UnKnownFont store
	    FontDirectory { %forall
		/Ffont exch store /Fname exch store
		% if the font was already touched, ignore it:
		Ffont /FontInfo known { %ifelse
		    Ffont /FontInfo get /realname known not
		}{ true } ifelse	% leaves boolean
		{ % if
		    % if UniqueID's match, grab it!
		    Dfont /UniqueID known Ffont /UniqueID known and {
			Dfont /UniqueID get Ffont /UniqueID get eq {
			    /tempfontname Fname store exit
			} if
		    } if
		} if % /realname is not there
	    } forall
	    tempfontname /UnKnownFont eq { %if
	      Dfont begin
		FontDirectory { %forall
		  /Ffont exch store /Fname exch store
		  % if CharStrings match, then compare FontMatrix.  If
		  % FontMatrix matches or the *second* elements match,
		  % (it might be oblique), then grab it.
		  Dfont /FontType known {
		    FontType 1 eq {
		      Dfont/CharStrings known Ffont/CharStrings known and {
			Dfont/CharStrings get Ffont/CharStrings get eq {
			  Dfont/FontMatrix known Ffont/FontMatrix known and {
			    Dfont/FontMatrix get Ffont/FontMatrix get
			    2 copy eq  3 1 roll
			    2 get exch 2 get eq or {
				/tempfontname Fname store exit
			    } if
			  } if
			} if
		      } if
		    } if
		  } if
		} forall
	      end
	    } if
	    tempfontname /UnKnownFont eq { %if
	      FontDirectory { %forall
		/Ffont exch store /Fname exch store
		  % if everything matches but some keys, grab it
		  true	% start with "true" on stack
		  Dfont { %forall
		    exch dup /Encoding eq 1 index /FID eq or { %ifelse
			pop pop
		    }{ % else
			dup Ffont exch known {
			    Ffont exch get ne { pop false exit } if
			}{ pop pop } ifelse
		    } ifelse
		  } forall
		  % use either "true" that was there, or "false" from loop
		  { %if
		      /tempfontname Fname store exit
		  } if
	      } forall
	    } if
 	    tempfontname /UnKnownFont eq {
		Dfont /Encoding get StandardEncoding eq
		substitutefonts or { %ifelse
		  % If there is no comparable fontdict already there, and
		  % if this is of FontType 1 and has StandardEncoding,
		  % we guess that this is a downloadable font, and ignore it
		    Dfont /FontName known {
			/tempfontname Dfont /FontName get store
		    }{
			/tempfontname /Courier store
		    } ifelse
		    (%substituting ) wout tempfontname writename writeNL
		    messages {
			(substituting: ) pr= tempfontname ==
		    } if
		    Dfont	% needed by *definefont below...
		}{ %else
		    (ERROR: Couldn't find original fontdict to match: ) print
		    Dfont /FontName get == flush
		    (Fonts in FontDirectory include:) r=
		    FontDirectory { pop (\040) print == } forall flush
		    stop
		} ifelse
	    } if
	    Dfont /FontInfo known not
	    Dfont /FontName known not or {
		Dfont dup length 3 add exch maxlength ge and { %if
		    % make slightly bigger version of current dictionary
		    Dfont maxlength 2 add dict begin
		    Dfont { def } forall
		    currentdict end /Dfont exch def
		} if
	    } if
	    Dfont dup begin
		/FontName 2 index def
		/FontInfo 5 dict def
		FontInfo begin
		    /realname tempfontname def
		    /pleasemap magicbool def
		    /pleasemap
			tempfontname findfont /Encoding get
			StandardEncoding eq
		    hidebool
		end
	    end
	} if
	*definefont
    } bdef

end %adobe_distill
/setpacking where { pop setpacking } if
%%EndProcSet: distill_guessfont 1.0 0

%%BeginProcSet: hacks 0.5 0
  % defeat the "transform round exch round exch itransform" trick:
    /round { } bdef
    /transform { dup type /arraytype eq { pop } if } bdef
    /itransform { dup type /arraytype eq { pop } if } bdef
  % redefine control-D:
    (\004) { (\n%%EOF) writeop } bdef
%%EndProcSet: hacks 0.5 0

langdon@lll-lcc.UUCP (Bruce Langdon) (07/14/89)

On our Sun 2's, the data returned by the printer is in a log file.
On our Sun 4, the log lists only the banner pages.
Did we install it incorrectly? There is a rumor that Transcript 
no longer keeps the printer back talk. Hope that's not true, since I
often have to debug PS things that didn't work.
How do we find out?
----------------------------------------------------------------------
	Bruce Langdon  L-472                   langdon@lll-lcc.llnl.gov
	Physics Department                     14363%mfe.mfenet@nmfecc.llnl.gov
	Lawrence Livermore National Laboratory langdon@ocfmail.ocf.llnl.gov
	Livermore, CA 94550                 (415) 422-5444
UUCP: ..{qantel,ucdavis,pyramid,harvard,topaz}!lll-lcc!langdon

cplai@daisy.UUCP (Chung-Pang Lai) (07/14/89)

In article <11613@orstcs.CS.ORST.EDU> pvo@oce.orst.edu (Paul V O'Neill) writes:
]My boss is using FrameMaker 1.3b on a Sun-3/50 running SunOS 3.5.  She wants
]to import some Postscript figures produced by a locally-written Postscript
]plotting package.  Today she discovered that she can only import Encapsulated
]Postscript.  
]
]Does anyone have, or know of, code, packages, or applications that will 
]convert garden-variety Postscript to Encapsulated Postscript?

And Glenn Reid replied:
] Sometimes you can manually add some of the comments and other syntactic
] sugar to the PostScript file to make it appear to be an Encapsulated
] PostScript file, but EPSF really means more than that.  It means that
] the program promises not to violate certain portability constraints,
] and adding comments doesn't provide that.

This is what I do to make FrameMaker 1.3b to take my PS program as an
EPSF file:	(Disclaimer: this may not work for other software)

1) Find out the bounding box of the output:
If you wrote the PS program, you know the coordinates of the bounding box.
For example, a 1" radius circle centered at (3",5") off the lower left corner
of the page is bounded by a box (2", 4"), (4", 6") where the first pair is
the lower left, and the second pair the upperright corner of the bounding box,
then you get the coordinate of the corners by multipy 72 per inch to get
(144 288 288 432) for the %%BoundingBox

If you did not write the PS file, send the PS to the printer.  Take out a
ruler and measure the bounding box on paper.  Get the value for the
%%BoundingBox as above.

2) change the first line to:
	%!PS-Adobe-2.0 EPSF-1.2

3) Add:
	%%BoundingBox: 144 288 288 432
	%%EndComments
(of course, replace the values with the actual value that you've just
figured out)

At the end of the file add:
	%%Trailer

The circle example above will look like the following:

%!PS-Adobe-2.0 EPSF-1.2
%%BoundingBox: 144 288 288 432
%%EndComments
newpath
216 360 72 0 360 arc
stroke
showpage
%%Trailer

As you can see, there is no Preview Image.  Hence FrameMaker will show
the box in gray (or white?)  You can grab the resize handle to scale
the picture or reposition it.  I'd recommand using the Scale command
and specify a percentage as scaling factor to preserve the aspect
ratio of the picture.  Rubberbanding using the mouse will usually
end up in a flattened or elongated picture.

The showpage can be left in there, FrameMaker redefines showpage as
no-op before printing the EPSF import.

As Glenn has pointed out, faking a EPSF file does not mean you get
a real EPSF file.  But it is worth trying.

-- 
.signature under construction ...
{pyramid, osu-cis, uunet, killer}!daisy!cplai    C.P. Lai
cplai%daisy.UUCP@uunet.UU.NET   cplai%daisy@killer.DALLAS.TX.USA
Daisy Systems Corp, 700B Middlefield Road, Mtn View CA 94039.  (415)960-6961

ttl@astroatc.UUCP (Tony Laundrie) (07/18/89)

In article <2537@lll-lcc.UUCP> langdon@lll-lcc.UUCP (Bruce Langdon) writes:
>
>On our Sun 4, the log lists only the banner pages.
>Did we install it incorrectly? There is a rumor that Transcript...

On our UNIX machine, only the banner pages are noted in /usr/adm/printer_log.
Output that comes from the laser printer is saved into a temporary file in the
spooling directory, /usr/spool/printer_name/errsXXXX.  Unfortunately, lpr
removes this file right after your job is finished.  There are several ways
to capture it:

   - Type 'tail -0f /usr/spool/printer_name/errs* > somefile' right after
     sending your job.  If you can't get the errs* file fast enough, insert
     a PostScript pause to your job like this:
         usertime 5000 add                    % current usertime + 5000 ms
         {dup usertime lt {pop exit} if} loop % wait for usertime to catch up

   OR

   - Modify your version of lpr so that it copies the errs* file to the
     mail file if the -m option is used.  Add these lines to printjob.c:
	 929,937c929
	 <           printf("\ncompleted successfully\n");
	 <           /* Copy the error file -- especially for PostScript
	 <              output that the user wants to see */
	 <           if ((fp = fopen(tmpfile, "r")) != NULL) {
	 <              while ((i = getc(fp)) != EOF)
	 <                   putchar(i);
	 <              (void) fclose(fp);
	 <           }
	 <           putchar ('\n');

Have fun.   ...uwvax!astroatc!ttl   ttl@astroatc.UUCP   Tony Laundrie