星火微课系统客户端
Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.

pdfwrite.ps 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397
  1. % Copyright (C) 1999, 2000, 2001 Aladdin Enterprises. All rights reserved.
  2. %
  3. % This software is provided AS-IS with no warranty, either express or
  4. % implied.
  5. %
  6. % This software is distributed under license and may not be copied,
  7. % modified or distributed except as expressly authorized under the terms
  8. % of the license contained in the file LICENSE in this distribution.
  9. %
  10. % For more information about licensing, please refer to
  11. % http://www.ghostscript.com/licensing/. For information on
  12. % commercial licensing, go to http://www.artifex.com/licensing/ or
  13. % contact Artifex Software, Inc., 101 Lucas Valley Road #110,
  14. % San Rafael, CA 94903, U.S.A., +1(415)492-9861.
  15. % $Id: pdfwrite.ps 9246 2008-11-27 01:58:54Z alexcher $
  16. % Writer for transmuting PDF files.
  17. % NOTES:
  18. % We do editing by replacing objects (in the cache) and then doing a
  19. % simple recursive walk with object renumbering.
  20. % Free variables:
  21. % RMap [per input file] (dict): input_obj# => output_obj#
  22. % PDFfile (file): current input file
  23. % OFile (file): current output file
  24. % XRef (dict): output_obj# => output_file_pos
  25. % ToWrite: 0..N-1 => [obj# gen#]
  26. .languagelevel 2 .setlanguagelevel
  27. .currentglobal true .setglobal
  28. /PDFWRDEBUG where { pop } { /PDFWRDEBUG false def } ifelse
  29. % ======== Long dictionary support =============== %
  30. % The key must be a non-negative iteger.
  31. /ld_dict { % <len> ld_dict <ldict>
  32. pop << 0 <<>> >>
  33. } bind def
  34. /ld_length { % <ldict> ld_length <length>
  35. 0 exch { exch pop length add } forall
  36. } bind def
  37. /ld_get { % <ldict> <key> ld_get <any>
  38. dup 3 1 roll -15 bitshift get exch get
  39. } bind def
  40. /ld_put { % <ldict> <key> <any> ld_put -
  41. 3 1 roll dup % any ldict key key
  42. 4 1 roll -15 bitshift % key any ldict key>>15
  43. 2 copy known {
  44. get % key any subdict
  45. 3 1 roll put % -
  46. } {
  47. 64 dict dup 6 1 roll % <<>> key any ldict key>>15 <<>>
  48. put put
  49. } ifelse % -
  50. } bind def
  51. /ld_known { % <ldict> <key> ld_known <bool>
  52. dup 3 1 roll -15 bitshift % key <<>> key<<15
  53. 2 copy known {
  54. get exch known
  55. } {
  56. pop pop pop //false
  57. } ifelse
  58. } bind def
  59. /ld_knownget { % <ldict> <key> ld_known false | <any> true
  60. dup 3 1 roll -15 bitshift % key <<>> key<<15
  61. 2 copy known {
  62. get exch .knownget
  63. } {
  64. pop pop pop //false
  65. } ifelse
  66. } bind def
  67. /ld_def { % <key> <any> ld_def -
  68. currentdict 3 1 roll ld_put
  69. } bind def
  70. /ld_forall { % <ldict> <proc} ld_forall -
  71. { forall exch pop } aload pop
  72. 4 2 roll 4 packedarray cvx forall
  73. } bind def
  74. /ld_clone { % <ldict> ld_clone <ldict copy>
  75. << exch { dup length dict copy } forall >>
  76. } bind def
  77. % ================ Object mapping ================ %
  78. % Initialize the object number and location map.
  79. /omapinit { % - omapinit -
  80. /RMap 100 ld_dict def
  81. /XRef 100 ld_dict def
  82. PDFWRDEBUG { (omapinit) = } if
  83. } bind def
  84. % Map an object number.
  85. /omapnew { % <oldobj#> omap <newobj#> <isnew>
  86. RMap 1 index ld_knownget {
  87. exch pop //false
  88. } {
  89. PDFWRDEBUG { (omap\() print dup =only } if
  90. RMap dup ld_length 1 add % old# <<>> len+1
  91. 2 index exch dup % old# <<>> old# len+1 len+1
  92. 5 1 roll % len+1 old# <<>> old# len+1
  93. ld_put pop //true % len+1 true
  94. PDFWRDEBUG { (\) = ) print 1 index = } if
  95. } ifelse
  96. } bind def
  97. /omap { % <oldobj#> omap <newobj#>
  98. omapnew pop
  99. } bind def
  100. % Save and restore the object map.
  101. % Note that currentomap either returns a copy or calls omapinit.
  102. /currentomap { % <copy> currentomap <omap>
  103. {
  104. [RMap ld_clone XRef ld_clone]
  105. } {
  106. [RMap XRef] omapinit
  107. } ifelse
  108. } bind def
  109. /setomap { % <omap> setomap -
  110. aload pop /XRef exch def /RMap exch def
  111. PDFWRDEBUG {
  112. (setomap: #Xref = ) print XRef ld_length =only
  113. (, #RMap = ) print RMap ld_length =
  114. } if
  115. } bind def
  116. % ================ Writing ================ %
  117. % ---------------- Low-level output ---------------- %
  118. % Write a string on the output file.
  119. /ows { % <string> ows -
  120. OFile exch writestring
  121. } bind def
  122. % ---------------- Scalars ---------------- %
  123. % Note that the '#' character isn't legal in a name unless it is a prefix
  124. % for a hex encoded character (for PDF 1.2 and later). The following assumes
  125. % that the names are already valid PDF 1.2+ names so that we can treat the
  126. % '#' as a legal character. The next two hex characters are already in the
  127. % set of valid name characters. PDF 1.1 and earlier allowed spaces in names
  128. % which probably wouldn't make it past the tokenizer anyway.
  129. /pdfnamechars
  130. (!"$&'*+,-.0123456789:;=?@ABCDEFGHIJKLMNOPQRSTUVWXYZ\\^_`abcdefghijklmnopqrstuvwxyz|~)
  131. readonly def
  132. /pdfwritename { % <name> pdfwritename -
  133. (/) ows .namestring {
  134. ( ) dup 0 4 -1 roll put
  135. //pdfnamechars 1 index search {
  136. pop pop pop
  137. } {
  138. pop 0 get 256 add 16 =string cvrs
  139. dup 0 (#) 0 get put
  140. } ifelse ows
  141. } forall
  142. } bind def
  143. % ---------------- Composite objects ---------------- %
  144. /pdfwriteprocs mark
  145. /resolveR { pdfwriteref }
  146. /O { pdfwritenewref }
  147. .dicttomark readonly def
  148. /pdfwritearray { % <array> pdfwritearray -
  149. dup xcheck {
  150. aload pop //pdfwriteprocs exch get exec
  151. } {
  152. % Because of a bug in Acrobat's parser for linearization parameters,
  153. % we have to include some whitespace after the opening [ (!).
  154. ([ ) ows { pdfwritevalue (\n) ows } forall (]) ows
  155. } ifelse
  156. } bind def
  157. /pdfwritedict { % <dict> pdfwritedict -
  158. dup xcheck {
  159. pdfwritestream
  160. } {
  161. (<<) ows {
  162. exch pdfwritevalue ( ) ows pdfwritevalue (\n) ows
  163. } forall (>>) ows
  164. } ifelse
  165. } bind def
  166. % ---------------- References ---------------- %
  167. /pdfwritenewref { % <newobj#> pdfwritenewref -
  168. OFile exch write=only ( 0 R) ows
  169. } bind def
  170. /pdfwriteref { % <obj#> <gen#> pdfwriteref -
  171. 1 index omapnew {
  172. ToWrite dup length 5 -2 roll 2 packedarray put
  173. } {
  174. exch pop exch pop
  175. } ifelse
  176. pdfwritenewref
  177. } bind def
  178. /pdfcopystring 200 string def
  179. /pdfwritestream { % <streamdict> pdfwritestream -
  180. % Remove File, FilePosition, and StreamKey;
  181. % optimize by replacing an indirect Length.
  182. dup dup length dict copy
  183. % Stack: origdict dict
  184. dup /File undef dup /FilePosition undef dup /StreamKey undef
  185. dup /Length known {
  186. dup /Length get dup oforce ne {
  187. dup /Length 2 copy oget put
  188. } if
  189. } {
  190. 1 index /File get dup
  191. 3 index /FilePosition get setfileposition
  192. dup 0 (endstream) /SubFileDecode filter flushfile
  193. .fileposition 9 sub
  194. 2 index /FilePosition get sub
  195. 1 index exch /Length exch put
  196. } ifelse
  197. exch dup /File get dup 3 -1 roll /FilePosition get setfileposition
  198. pdfcopystream
  199. } bind def
  200. % We put copying the stream contents in separate procedures so that we
  201. % can replace this function if desired.
  202. /pdfcopybytes { % <fromfile> <tofile> <length> pdfcopybytes -
  203. {
  204. dup 0 eq { exit } if
  205. //pdfcopystring 0 2 index 2 index length .min getinterval
  206. 3 index exch readstring 3 1 roll
  207. 3 index 1 index writestring length sub exch not { exit } if
  208. } loop pop pop pop
  209. } bind def
  210. /pdfcopystream { % <newstreamdict> <file> pdfcopystream -
  211. % (file has been positioned)
  212. 1 index pdfwritevalue (stream\n) ows
  213. exch /Length get OFile exch pdfcopybytes
  214. (endstream) ows
  215. } bind def
  216. % ---------------- General values/objects ---------------- %
  217. /pdfwritetypes mark
  218. % Scalars
  219. /nulltype { pop (null) ows } bind
  220. /integertype { =string cvs ows } bind
  221. /booleantype 1 index
  222. /realtype {
  223. =string cvs
  224. (e) search { % PDF has no exponential format
  225. exch pop % exp pre
  226. exch cvi exch
  227. (-) anchorsearch { ows } if
  228. (.) search {
  229. exch pop % exp (frac) (int)
  230. 1 index length % exp (frac) (int) len
  231. 3 1 roll % exp len (frac) (int)
  232. exch concatstrings % exp len (int_frac)
  233. 3 1 roll sub % (int_frac) exp-len
  234. exch % exp-len (int_frac)
  235. } if % exp (mant)
  236. 1 index 0 ge {
  237. ows { (0) ows } repeat (.) ows
  238. } {
  239. dup length % exp (mant) len
  240. 3 -1 roll add % (mant) exp+len
  241. dup 0 le {
  242. (0.) ows neg { (0) ows } repeat ows
  243. } {
  244. 2 copy 0 exch getinterval ows
  245. (.) ows
  246. 1 index length 1 index sub getinterval ows
  247. } ifelse
  248. } ifelse
  249. } {
  250. ows
  251. } ifelse
  252. } bind
  253. /stringtype { OFile exch write===only } bind
  254. /nametype { pdfwritename } bind
  255. % Composite/reference objects
  256. /arraytype { pdfwritearray } bind
  257. /packedarraytype 1 index
  258. /dicttype { pdfwritedict } bind
  259. .dicttomark readonly def
  260. /pdfwritevalue { % <obj> pdfwritevalue -
  261. PDFWRDEBUG { (****Writing: ) print dup === flush } if
  262. //pdfwritetypes 1 index type get exec
  263. } bind def
  264. % We make pdfwriteobjdef a separate procedure for external use.
  265. /pdfwriteobjheader { % <newobj#> pdfwriteobjheader -
  266. XRef 1 index OFile .fileposition ld_put
  267. PDFWRDEBUG { (XRef\() print dup =only (\) = ) print XRef 1 index ld_get = } if
  268. OFile exch write=only ( 0 obj\n) ows
  269. } bind def
  270. /pdfwriteobjdef { % <newobj#> <value> pdfwriteobjdef -
  271. exch pdfwriteobjheader
  272. pdfwritevalue (\nendobj\n) ows
  273. } bind def
  274. /pdfwriteobj { % <obj#> <gen#> pdfwriteobj -
  275. 1 index exch resolveR exch omap exch pdfwriteobjdef
  276. } bind def
  277. % ---------------- File-level entities ---------------- %
  278. % Write a PDF file header.
  279. % Free variables: OFile, PDFversion.
  280. /pdfwriteheader { % - pdfwriteheader -
  281. (%PDF-) ows OFile PDFversion write=
  282. (%\347\363\317\323\n) ows
  283. } bind def
  284. % Write a cross-reference table and trailer.
  285. /pdfwritexref { % <firstobj#> <#objs> pdfwritexref -
  286. (xref\n) ows
  287. OFile 2 index write=only ( ) ows OFile 1 index write=
  288. 1 index add 1 sub 1 exch {
  289. dup 0 eq {
  290. pop (0000000000 65535 f \n) ows
  291. } {
  292. XRef exch ld_get 1000000000 add =string cvs
  293. dup 0 (0) 0 get put
  294. ows ( 00000 n \n) ows
  295. } ifelse
  296. } for
  297. } bind def
  298. /pdfwritetrailer { % <trailer> pdfwritetrailer -
  299. (trailer\n) ows
  300. % Since we always write a complete "classic" xref, the Trailer may need to be adjusted:
  301. % - remove keys that pertain to xref-streams and hybrid-xref PDFs;
  302. % - if it's a PDF stream, turn it into a PDF dict by removing keys used for
  303. % PDF streams (both standard and GS-specific), and the executable attribute
  304. dup /XRefStm known 1 index xcheck or {
  305. dup length dict copy
  306. dup {/Type/Index/W /XRefStm /Filter/DecodeParms/Length/File/FilePosition} {
  307. undef dup
  308. } forall pop
  309. % note: the executable attribute is "removed" by not being copied
  310. } if
  311. pdfwritevalue
  312. (\n) ows
  313. } bind def
  314. /pdfwritestartxref { % <startpos> pdfwritestartxref -
  315. (startxref\n) ows OFile exch write=
  316. (%%EOF\n) ows
  317. } bind def
  318. % ================ Top-level control ================ %
  319. /pdfwrite { % <file> <trailer> pdfwrite -
  320. 10 dict begin
  321. /trailer exch def
  322. /OFile exch def
  323. /ToWrite 100 dict def
  324. omapinit
  325. % Write the PDF file header.
  326. pdfwriteheader
  327. % Write the objects.
  328. trailer {
  329. exch pop dup xcheck { % The only executable objects are references.
  330. aload pop pop pdfwriteobj
  331. } {
  332. pop
  333. } ifelse
  334. } forall
  335. % Walk the object graph.
  336. {
  337. ToWrite dup length dup 0 eq { pop pop exit } if
  338. 1 sub 2 copy get 3 1 roll undef aload pop pdfwriteobj
  339. } loop
  340. % Write the xref table and trailer.
  341. /xref OFile fileposition def
  342. 0 XRef ld_length 1 add pdfwritexref
  343. trailer dup length 1 add dict copy trailer xcheck { cvx } if
  344. dup /Size XRef ld_length 1 add put pdfwritetrailer
  345. xref pdfwritestartxref
  346. end
  347. } bind def
  348. .setglobal .setlanguagelevel