diff options
Diffstat (limited to 'lib/ps2epsi.ps')
-rw-r--r-- | lib/ps2epsi.ps | 385 |
1 files changed, 157 insertions, 228 deletions
diff --git a/lib/ps2epsi.ps b/lib/ps2epsi.ps index 86f1d2ff..54621f92 100644 --- a/lib/ps2epsi.ps +++ b/lib/ps2epsi.ps @@ -1,4 +1,4 @@ -% Copyright (C) 2001-2019 Artifex Software, Inc. +% Copyright (C) 2001-2020 Artifex Software, Inc. % All Rights Reserved. % % This software is provided AS-IS with no warranty, either express or @@ -11,234 +11,163 @@ % Refer to licensing information at http://www.artifex.com or contact % Artifex Software, Inc., 1305 Grant Avenue - Suite 200, Novato, % CA 94945, U.S.A., +1(415)492-9861, for further information. -% - -% Convert an arbitrary PostScript file to an EPSI file. -% -% Please do not contact these users if you have questions. They no longer -% have the time, interest, or current expertise to keep this code working. -% If you find bugs, please send proposed fixes to bug-gs@ghostscript.com. -% -% Bug fix 2002-04-20 by rayjj: Bounding box was incorrect since it depended -% on the dither pattern and gray shade at the boundary. Changed to use -% 8-bit grayscale preview image to allow correct bounding box (at the -% expense of a 8x larger preview image). Also moved .setsafe until after -% the device and file operations are complete (but still before the input -% file is processed. -% Bug fix 2000-04-11 by lpd: if a font didn't have a FontName (which is the -% case for bitmap fonts produced by recent versions of dvips), setfont -% caused an error. -% Bug fix 8/21/99 by lpd: many of the margin and width computations were -% wrong (off by 1). The code only "worked" because the bugs were -% (mostly) in conservative directions. -% Modified 3/17/98 by lpd to make it possible to run this file without -% running the ps2epsi script first, for debugging. -% Bug fix 9/29/97 by lpd <ghost@aladdin.com>: if the page size wasn't an -% exact multiple of 8 bits, an incorrect bounding box (or a rangecheck -% error) could occur. -% Patched 7/26/95 by -% Greg P. Kochanski <gpk@bell-labs.com> -% to add many new DSC comments and make the comments conforming. -% Original version contributed by -% George Cameron <george@bio-medical-physics.aberdeen.ac.uk> -% -% Initialize, and redefine copypage and showpage. - -% ps2edict is normally defined in the pre-loaded code created by the -% ps2epsi script. -/ps2edict where { pop } { /ps2edict 25 dict def } ifelse -ps2edict begin - - % The main procedure - /ps2epsi - { - % bbox written to outfile by bbox device from ps2epsi command file - outfile (r) file /epsifile exch def - /BBoxString epsifile 256 string readline pop def - /HiresBBoxString epsifile 256 string readline pop def - epsifile closefile - % Open the file - outfile (w) file /epsifile exch def - % Get the device parameters - currentdevice getdeviceprops .dicttomark - /HWSize get aload pop - /devheight exch def - /devwidth exch def - matrix defaultmatrix - /devmatrix exch def - % Make a corresponding 8-bit deep memory device - devmatrix devwidth devheight - 256 string 0 1 255 { 1 index exch dup 255 exch sub put } for - makeimagedevice - /arraydevice exch def - arraydevice - % Turn on anti-aliasing - mark /TextAlphaBits 4 /GraphicsAlphaBits 4 6 -1 roll - putdeviceprops - setdevice % (does an erasepage) - /rowwidth devwidth def - /row rowwidth string def - /zerorow rowwidth string def % all zero - % Replace the definition of showpage - userdict /showpage { ps2edict begin epsipage end } bind put - userdict /setfont { ps2edict begin epsisetfont end } bind put - userdict /setpagedevice /pop load put - } bind def - - /epsifontdict 100 dict def - - /epsisetfont - { - % code here keeps a list of font names in dictionary epsifontdict - /tmpfont exch def - tmpfont /FontName known { - /tmpfontname tmpfont /FontName get def - epsifontdict tmpfontname known not { epsifontdict tmpfontname 0 put } if - epsifontdict tmpfontname 2 copy get 1 add put - } if - tmpfont setfont - } bind def - -% Get a scan line from the memory device, zeroing any bits beyond -% the device width. -/getscanline { % <device> <y> <string> getscanline <string> - dup 4 1 roll copyscanlines pop - 16#ff00 devwidth 7 and neg bitshift 255 and - dup 0 ne { - 1 index dup length 1 sub 2 copy get 4 -1 roll and put - } { - pop - } ifelse -} bind def - -/margintest { % <y-start> <step> <y-limit> margintest <y-non-blank> - % <y-start> <step> <y-limit> margintest - - { dup arraydevice exch row getscanline - zerorow ne { exit } if pop - } for -} bind def - - /epsiNameStr 200 string def - /epsiNpages 0 def - /epsiNpageStr 20 string def - /epsipage - { - /epsiNpages epsiNpages 1 add def - /loopcount devheight 1 sub def - - % Find top margin -- minimum Y of non-blank scan line. - -1 0 1 loopcount margintest - dup -1 eq { (blank page!!\n) print quit }{ exch pop } ifelse - /tm exch def - - % Find bottom margin -- maximum Y of non-blank scan line. - loopcount -1 0 margintest - /bm exch def - - % Initialise limit variables - /loopcount rowwidth 1 sub def - /lm loopcount def - /rm 0 def - - % Find left and right boundaries of image - tm 1 bm - { % Get more data - arraydevice exch row getscanline pop - % Scan from left to find first non-zero element - % We save first the element, then the index - -1 0 1 loopcount - { dup row exch get 0 ne { exch pop exit }{ pop } ifelse - } for - % If we found -1, row is blank .. - dup -1 ne - { % Find the leftmost index - dup lm lt - % If the new index is less, we save index and element - { /lm exch def } { pop } ifelse - % Now find the rightmost index - loopcount -1 0 - { dup row exch get 0 ne { exit }{ pop } ifelse - } for - dup rm gt - % If the new index is greater, we save index and element - { /rm exch def } { pop } ifelse - } { - pop - } ifelse - } for - - % Write out the magic string and bounding box information - epsifile (%!PS-Adobe-2.0 EPSF-1.2\n) writestring - /epsititle where { pop epsifile epsititle writestring } if - /epsicreator where { pop epsifile epsicreator writestring } if - /epsicrdt where { pop epsifile epsicrdt writestring } if - /epsifor where { pop epsifile epsifor writestring } if - epsifile flushfile - - % Write out the page count: - epsifile (%%Pages: ) writestring - epsifile epsiNpages epsiNpageStr cvs writestring - epsifile (\n) writestring - epsifile flushfile - - % Write out the list of used fonts: - epsifile (%%DocumentFonts:) writestring - epsifontdict { - epsifile ( ) writestring - pop epsiNameStr cvs epsifile exch writestring - } forall - epsifile (\n) writestring - epsifile flushfile - - epsifile BBoxString writestring epsifile (\n) writestring - epsifile HiresBBoxString writestring epsifile (\n) writestring - - % Define character and bit widths for the output line buffer: - /cwidth rm lm sub 1 add def - /out cwidth string def - - epsifile (%%EndComments\n\n) writestring - epsifile (%%BeginProlog\n) writestring - epsifile (%%BeginPreview: ) writestring - epsifile cwidth write==only epsifile ( ) writestring - epsifile bm tm sub 1 add write==only epsifile ( 8 ) writestring - epsifile bm tm sub 1 add - cwidth 39 add 40 idiv mul write== - epsifile flushfile - - gsave - - tm 1 bm - { % Get a scan line interval from the array device - arraydevice exch row copyscanlines lm cwidth getinterval - % Write out the hex data as 40 bytes per line (82 chars) - 0 40 cwidth - { epsifile (% ) writestring - epsifile exch 2 index exch - dup cwidth exch sub 40 .min getinterval writehexstring - epsifile (\n) writestring - } for - pop - } for - - epsifile (%%EndImage\n) writestring - epsifile (%%EndPreview\n) writestring - epsifile flushfile - grestore - erasepage initgraphics - - DonePage 0 1 put - } bind def - -(outfile) getenv - { /outfile exch def - ps2epsi - - /DonePage 1 string def - (%stdin) (r) file cvx execute0 - DonePage 0 get 0 eq { showpage } if +% Convert a PostScript file to an EPSI file, adding the Preview Image. + +% If the file is already EPSF, then skip the creation of an EPSF, and +% only add the preview. A warning is issued if the %%Pages: comment +% indicates that there is more than a single page in the input file. + +% Expected invocation: +% gs -q -dNOOUTERSAVE -dNODISPLAY -dLastPage=1 -sOutputFile=out.epsi --permit-file-read=in.ps -- ps2epsi.ps in.ps + +% Usually this will be invoked by the ps2epsi script (or .bat or .cmd versions) + +false % no errors from initial param check +% NOOUTERSAVE is needed for the SAVE to not remove the tempfile (if one was needed) +vmstatus pop pop 0 gt { (Error: missing -dNOOUTERSAVE option) = pop true } if +% NODISPLAY may not be strictly needed, but we don't want to open the default device +/NODISPLAY where { pop } { (Error: missing -dNODISPLAY option) = pop true } ifelse +% LastPage is needed if we are using eps2write on a PostScript (or PDF) file that has multiple pages. +/LastPage where { pop } { (Error: missing -dLastPage option) = pop true } ifelse +% OutputFile is needed so that it gets on the permit-file-writing list +/OutputFile where { pop } { (Error: missing -sOutputFile option) = pop true } ifelse + +.shellarguments not count 3 lt or count -1 roll or +{ + (usage: gs -q -dNOOUTERSAVE -dNODISPLAY -dLastPage=1 -sOutputFile=out.epsi --permit-file-read=in.eps -- ps2epsi.ps in.ps) = + quit +} { + dup /InputFile exch def + (r) file /I exch def +} ifelse + +/O OutputFile (w) file def + +/S 65535 string def + +/R { I S readline not { (Error: Unexpected end of file.) = quit } if } bind def +/WL { O exch writestring O (\n) writestring } bind def % Write with linefeed +/TName null def + +/EPSFheader (%!PS-Adobe-3.0 EPSF-3.0) def +% Read the header to check if this file was EPSF +R +dup EPSFheader ne { + % InputFile was not EPSF + pop % discard the first line of the InputFile + % run the file through eps2write (into a tempfile) to make an EPSF + (_ps2epsi) (w+) .tempfile closefile /TName exch def + /SAVE save def + (eps2write) finddevice mark /OutputFile TName 3 index putdeviceprops pop + setdevice + InputFile run + SAVE restore + /I TName (r) file def + R +} if +WL % Write the first line (either from InputFile or the tempfile + +% From the "5002 Encapsulated PostScript File Format Specification Version 3.0 1 May 1992" +% The preview section must appear after the header comment section, but +% before the document prologue definitions. That is, it should immediately +% follow the %%EndComments: line in the EPS file. +{ % loop until we see the %%EndComments line, writing those lines to output + R + dup (%%EndComments) anchorsearch exch pop { % discard the match or extra copy of the string + pop exit % found it } if + % Check the %%Pages: comment to issue a warning if there is more than one page. + dup (%%Pages:) anchorsearch exch pop { % discard the match or extra copy of the string + cvi 1 gt { + (Warning: EPSI files can only have 1 page, Only the first page will be in the preview.) = + } if + } if + % Collect the BoundingBox data that will be used when generating the preview + dup (%%BoundingBox:) anchorsearch exch pop { % discard the match or extra copy of the string + mark + exch token not { (Error: invalid BoundingBox parameters) = quit } if + exch token not { (Error: invalid BoundingBox parameters) = quit } if + exch token not { (Error: invalid BoundingBox parameters) = quit } if + exch token not { (Error: invalid BoundingBox parameters) = quit } if + exch pop ] + /BBox exch def + % Preview dimensions + /PWidth BBox dup 2 get exch 0 get sub def + /PHeight BBox dup 3 get exch 1 get sub def + } if + WL % send to output file with linefeed. +} loop + +WL % send to output file with linefeed. + +% If the InputFile already has a preview, skip past it +R +dup (%%BeginPreview) anchorsearch exch pop { % discard the match or extra copy of the string + pop + % Read lines until after the %%EndPreview + { + R + (%%EndPreview) anchorsearch exch pop { % discard the match or extra copy of the string + pop pop exit % found it + } if + } loop + % Get the next line for use after the generated preview + R +} +if +/LineAfterEndComments exch def + +//null (w+) .tempfile +closefile % will be opened by bit device +/Pname exch def + +(bit) selectdevice +<< + /GrayValues 256 % Gray, not monochrome + /OutputFile Pname + /TextAlphaBits 4 + /GraphicsAlphaBits 4 + /LastPage 1 % TBD: does this work? + /.IgnoreNumCopies true + /Install { BBox 0 get neg BBox 1 get neg translate { 1.0 exch sub } settransfer } % EPSI 00 is white + /HWResolution [ 72. 72. ] + /PageSize [ PWidth PHeight ] +>> setpagedevice + +InputFile run + +/P Pname (r) file def % Preview data file +/SP PWidth string def % One string per image line + +% Write the preview +O (%%BeginPreview: ) writestring +O PWidth write==only O ( ) writestring +O PHeight write==only O ( 8 ) writestring +O PHeight PWidth 39 add 40 idiv mul write== % 40 bytes per line +O flushfile +0 1 PHeight 1 sub { + pop + P SP readstring pop + 0 40 PWidth { + O (% ) writestring % 82 bytes on each line, plus EOL + SP exch 40 PWidth 2 index sub .min getinterval + O exch writehexstring + O (\n) writestring + } for + pop +} for +(%%EndPreview) WL + +% Write the line that followed the %%EndComments +LineAfterEndComments WL + +% Copy the remainder of the inputfile +{ + I S readstring exch O exch writestring not { exit } if +} loop + +% If we created a tempfile, delete it +TName null ne { TName deletefile } if -end quit |