home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Carousel Volume 2 #1
/
carousel.iso
/
mactosh
/
lang
/
distill.sit
/
still.ps
< prev
Wrap
Text File
|
1989-04-03
|
69KB
|
2,199 lines
%!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 Mar 15 12:46:06 1989
%%VMUsage: 44036 (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 10 edit 08)) 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
/cachedir 60 dict def % how many font dicts to cache (optimization)
/includeprologue true def % output files with/without prologue
%
% 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!
%
% MANY USES:
% * If you archive documents in PostScript format, they can be
% made 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 these 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)
%
% KNOWN PROBLEMS:
% Clipping isn't handled correctly.
%
% I'm not convinced that the bounding box for images is right.
%
% 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 definitely 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
% 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
%%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
%%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 120 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
%%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.95\n) writestring
}{ %else
fd (%%DocumentNeededProcSets: Adobe_distill 0.95\n) writestring
} ifelse
fd (%%EndComments\n) writestring
} bdef
/writeprologue { %def % :
writecomments
includeprologue { %ifelse
mark
(%%BeginProcSet: Adobe_distill 0.95)
(/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)
( /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)
( /MF { findfont exch makefont setfont } bdef)
( /DF { findfont exch scalefont setfont 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.95)
% 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.95\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
% 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 .001; compensate for roundoff
dup type /realtype eq { %if
1000 mul truncate 1000 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
/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 writehexstring (> ) 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 { writenum } 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 num>128 was found
str1 search {
quotefix % string previous to num>128
(\\) wout % the backslash
% write suspicious char as octal
0 get 8 scratch cvrs % padding with leading 0 as needed
dup length 3 exch sub { (0) wout } repeat wout
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
%%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
% 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
} 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 cachedir exch 20 dict put % allow 20 point sizes
cachedir exch get % ptsize dict
exch fontcount put
} bdef
/addfontsize { %def
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
/FontName where { pop FontName }{
defaultfontname
} ifelse
} ifelse
}{ %else
/FontName where { pop FontName }{
defaultfontname
} ifelse
} ifelse
store
/definefontname
/FontName where { pop FontName }{
defaultfontname
} 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
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
(DF) writeop
} ifelse
}{ %else if you DON'T find the name in the cache
/fontcount ++
dup definefontname registerfont
(/F) wout fontcount writenum
writenum
origfontname
/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
(DF) writeop
} ifelse
}{ %else
% need either "makefont" or rotated coordinate system
pop pop $fontscale aload pop curfontmtx astore
dup 4 ScaleMatrix 4 get put
dup 5 ScaleMatrix 5 get put % no translate
writenumarray
origfontname
/FontInfo where {
pop FontInfo /pleasemap known
}{ false } ifelse { %ifelse
writeRname
}{ (/) wout writename } ifelse
(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 ne 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
%%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
%%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 /FontType known {
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 /FontType known {
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 /FontType known {
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 /FontType known {
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 /FontType known {
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 /FontType known {
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
writepath
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
(f) writeop
} 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
(eofill) writeop
} if
eofill
} bdef
/stroke { %def
?distilling cvbool { %if
fillguts
?simplepath { %ifelse
generalstate graphicstate
simplepath aload pop writepair writepair (l) writeop
/?simplepath false store
}{ % else
closed { (cp ) wout } if
(s) writeop
} 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 writehexstring 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 writehexstring 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
/lastshowpage true hidebool
/begunpage false hidebool
/PAGEvec 0 hideval
*showpage
(%%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
% checksetup
} 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
%%BeginProcSet: distill_guessfont 1.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 dup length 2 add exch maxlength ge and { %if
% make slightly bigger version of current dictionary
pop currentdict end
dup maxlength 1 add dict begin
{ def } forall currentdict
} if
/FontInfo 5 dict def
FontInfo begin
/realname 2 index def
/pleasemap magicbool def
/pleasemap false hidebool
end
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
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 dup begin
/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
%%BeginProcSet: hacks 0.5
% 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