You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

172 lines
5.9 KiB

1 month ago
  1. % Copyright (C) 2001-2023 Artifex Software, Inc.
  2. % All Rights Reserved.
  3. %
  4. % This software is provided AS-IS with no warranty, either express or
  5. % implied.
  6. %
  7. % This software is distributed under license and may not be copied,
  8. % modified or distributed except as expressly authorized under the terms
  9. % of the license contained in the file LICENSE in this distribution.
  10. %
  11. % Refer to licensing information at http://www.artifex.com or contact
  12. % Artifex Software, Inc., 39 Mesa Street, Suite 108A, San Francisco,
  13. % CA 94129, USA, for further information.
  14. % Convert a PostScript file to an EPSI file, adding the Preview Image.
  15. % If the file is already EPSF, then skip the creation of an EPSF, and
  16. % only add the preview. A warning is issued if the %%Pages: comment
  17. % indicates that there is more than a single page in the input file.
  18. % Expected invocation:
  19. % gs -q -dNOOUTERSAVE -dNODISPLAY -dLastPage=1 -sOutputFile=out.epsi --permit-file-read=in.ps -- ps2epsi.ps in.ps
  20. % Usually this will be invoked by the ps2epsi script (or .bat or .cmd versions)
  21. false % no errors from initial param check
  22. % NOOUTERSAVE is needed for the SAVE to not remove the tempfile (if one was needed)
  23. vmstatus pop pop 0 gt { (Error: missing -dNOOUTERSAVE option) = pop true } if
  24. % NODISPLAY may not be strictly needed, but we don't want to open the default device
  25. /NODISPLAY where { pop } { (Error: missing -dNODISPLAY option) = pop true } ifelse
  26. % LastPage is needed if we are using eps2write on a PostScript (or PDF) file that has multiple pages.
  27. /LastPage where { pop } { (Error: missing -dLastPage option) = pop true } ifelse
  28. % OutputFile is needed so that it gets on the permit-file-writing list
  29. /OutputFile where { pop } { (Error: missing -sOutputFile option) = pop true } ifelse
  30. .shellarguments not count 3 lt or count -1 roll or
  31. {
  32. (usage: gs -q -dNOOUTERSAVE -dNODISPLAY -dLastPage=1 -sOutputFile=out.epsi --permit-file-read=in.eps -- ps2epsi.ps in.ps) =
  33. quit
  34. } {
  35. dup /InputFile exch def
  36. (r) file /I exch def
  37. } ifelse
  38. /O OutputFile (w) file def
  39. /S 65535 string def
  40. /R { I S readline not { (Error: Unexpected end of file.) = quit } if } bind def
  41. /WL { O exch writestring O (\n) writestring } bind def % Write with linefeed
  42. /TName null def
  43. /EPSFheader (%!PS-Adobe-3.0 EPSF-3.0) def
  44. % Read the header to check if this file was EPSF
  45. R
  46. dup EPSFheader ne {
  47. % InputFile was not EPSF
  48. pop % discard the first line of the InputFile
  49. % run the file through eps2write (into a tempfile) to make an EPSF
  50. (_ps2epsi) (w+) .tempfile closefile /TName exch def
  51. /SAVE save def
  52. << /OutputDevice /eps2write /OutputFile TName >> setpagedevice
  53. InputFile run
  54. SAVE restore
  55. /I TName (r) file def
  56. R
  57. } if
  58. WL % Write the first line (either from InputFile or the tempfile
  59. % From the "5002 Encapsulated PostScript File Format Specification Version 3.0 1 May 1992"
  60. % The preview section must appear after the header comment section, but
  61. % before the document prologue definitions. That is, it should immediately
  62. % follow the %%EndComments: line in the EPS file.
  63. { % loop until we see the %%EndComments line, writing those lines to output
  64. R
  65. dup (%%EndComments) anchorsearch exch pop { % discard the match or extra copy of the string
  66. pop exit % found it
  67. } if
  68. % Check the %%Pages: comment to issue a warning if there is more than one page.
  69. dup (%%Pages:) anchorsearch exch pop { % discard the match or extra copy of the string
  70. cvi 1 gt {
  71. (Warning: EPSI files can only have 1 page, Only the first page will be in the preview.) =
  72. } if
  73. } if
  74. % Collect the BoundingBox data that will be used when generating the preview
  75. dup (%%BoundingBox:) anchorsearch exch pop { % discard the match or extra copy of the string
  76. mark
  77. exch token not { (Error: invalid BoundingBox parameters) = quit } if
  78. exch token not { (Error: invalid BoundingBox parameters) = quit } if
  79. exch token not { (Error: invalid BoundingBox parameters) = quit } if
  80. exch token not { (Error: invalid BoundingBox parameters) = quit } if
  81. exch pop ]
  82. /BBox exch def
  83. % Preview dimensions
  84. /PWidth BBox dup 2 get exch 0 get sub def
  85. /PHeight BBox dup 3 get exch 1 get sub def
  86. } if
  87. WL % send to output file with linefeed.
  88. } loop
  89. WL % send to output file with linefeed.
  90. % If the InputFile already has a preview, skip past it
  91. R
  92. dup (%%BeginPreview) anchorsearch exch pop { % discard the match or extra copy of the string
  93. pop
  94. % Read lines until after the %%EndPreview
  95. {
  96. R
  97. (%%EndPreview) anchorsearch exch pop { % discard the match or extra copy of the string
  98. pop pop exit % found it
  99. } if
  100. } loop
  101. % Get the next line for use after the generated preview
  102. R
  103. }
  104. if
  105. /LineAfterEndComments exch def
  106. //null (w+) .tempfile
  107. closefile % will be opened by bit device
  108. /Pname exch def
  109. (bit) selectdevice
  110. <<
  111. /GrayValues 256 % Gray, not monochrome
  112. /OutputFile Pname
  113. /TextAlphaBits 4
  114. /GraphicsAlphaBits 4
  115. /LastPage 1 % TBD: does this work?
  116. /.IgnoreNumCopies true
  117. /Install { BBox 0 get neg BBox 1 get neg translate { 1.0 exch sub } settransfer } % EPSI 00 is white
  118. /HWResolution [ 72. 72. ]
  119. /PageSize [ PWidth PHeight ]
  120. >> setpagedevice
  121. InputFile run
  122. /P Pname (r) file def % Preview data file
  123. /SP PWidth string def % One string per image line
  124. % Write the preview
  125. O (%%BeginPreview: ) writestring
  126. O PWidth write==only O ( ) writestring
  127. O PHeight write==only O ( 8 ) writestring
  128. O PHeight PWidth 39 add 40 idiv mul write== % 40 bytes per line
  129. O flushfile
  130. 0 1 PHeight 1 sub {
  131. pop
  132. P SP readstring pop
  133. 0 40 PWidth {
  134. O (% ) writestring % 82 bytes on each line, plus EOL
  135. SP exch 40 PWidth 2 index sub .min getinterval
  136. O exch writehexstring
  137. O (\n) writestring
  138. } for
  139. pop
  140. } for
  141. (%%EndPreview) WL
  142. % Write the line that followed the %%EndComments
  143. LineAfterEndComments WL
  144. % Copy the remainder of the inputfile
  145. {
  146. I S readstring exch O exch writestring not { exit } if
  147. } loop
  148. % If we created a tempfile, delete it
  149. TName null ne { TName deletefile } if
  150. quit